【问题标题】:Get Name of Action/Func Delegate获取动作/功能委托的名称
【发布时间】:2009-09-29 23:31:28
【问题描述】:

我有一个奇怪的情况,我需要将委托的名称作为字符串获取。我有一个看起来像这样的通用方法。

private T Get<T>(T task, Action<T> method) where T : class
{
  string methodName = method.Method.Name //Should return Bark
}

我这样称呼它

private void MakeDogBark()
{
  dog = Get(dog, x=>x.Bark());
}

但我没有看到“Bark”,而是看到了"&lt;MakeDogBark&gt;b__19"。所以看起来它给了我进行初始调用的方法名称,而不是委托的名称。

有人知道怎么做吗?

【问题讨论】:

    标签: c#


    【解决方案1】:

    它为您提供了代表操作的方法名称。这恰好是使用 lambda 表达式实现的。

    您目前有一个委托,反过来调用 Bark。如果您想直接使用Bark,则需要为Bark 方法创建一个开放委托,这可能不是非常简单。那是假设您实际上想要调用它。如果您不需要调用它,或者您知道无论如何都会在第一个参数上调用它,您可以使用:

    private T Get<T>(T task, Action method) where T : class
    {
       string methodName = method.Method.Name //Should return Bark
    }
    
    private void MakeDogBark()
    {
       dog = Get(dog, dog.Bark);
    }
    

    可以通过将参数设置为表达式树而不是委托来解决这个问题,但它只有在 lambda 表达式只是一个方法调用时才有效。

    【讨论】:

    • 效果很好。我不需要执行它,但我必须将方法名称传递给一个可以处理它的类。我希望调用者的类型安全而不是只接受一个字符串,而必须给我一个真正的方法。一如既往,你是男人:)
    • @Jon 有没有办法用泛型方法做同样的事情?
    • @ArnabChakraborty:您还必须指定类型参数,但我相信它会起作用。不过现在还不能轻易尝试。
    • 在哪里可以找到有关用于生成“b__19”字符串的命名约定的更多信息?就我而言,我看到的是“b__21_0”。谢谢。
    • @Sabuncu:这不是约定问题,只是编译器决定使用什么。除了该名称在常规 C# 中无效之外,没有任何保证。
    【解决方案2】:

    您可以通过将参数设为表达式而不是委托来获取方法调用的名称,就像 Jon 提到的那样

    private T Get<T>(T task, Expression<Action<T>> method) where T : class
    {
        if (method.Body.NodeType == ExpressionType.Call)
        {
            var info = (MethodCallExpression)method.Body;
            var name = info.Method.Name; // Will return "Bark"
        }
    
        //.....
    }
    

    【讨论】:

    • 所以你是说它会被称为Get&lt;MyClass&gt;(x =&gt; x.DoSomething(Arg1))?如果您只想以类型安全的方式将方法作为委托传递,但不调用它,例如 Get&lt;MyClass&gt;(x =&gt; x.DoSomething),该怎么办?
    • 是的。本质上,有没有办法在 C# 5 中从 C# 6 执行 nameof 运算符?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    • 2011-04-09
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    相关资源
    最近更新 更多