获取Action/Func Delegate的名称

Ada*_*dam 44 c#

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

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

而我这样称呼它

private void MakeDogBark()
{
  dog = Get(dog, x=>x.Bark());
}
Run Code Online (Sandbox Code Playgroud)

但我没有看到"树皮",而是看到了这一点"<MakeDogBark>b__19".所以看起来它给了我初始调用的方法名称而不是委托的名称.

有人知道怎么做吗?

Jon*_*eet 66

它为您提供了该方法的名称,该方法是委托的操作.这恰好是使用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);
}
Run Code Online (Sandbox Code Playgroud)

可以通过使参数成为表达式树而不是委托来绕过这个,但是只有当lambda表达式只是一个方法调用时它才会起作用.


Roh*_*est 7

您可以通过使参数成为表达式而不是委托来获取方法调用的名称,就像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"
    }

    //.....
}
Run Code Online (Sandbox Code Playgroud)

  • 所以你说它会被称为`Get <MyClass>(x => x.DoSomething(Arg1))`?如果您只是希望以类型安全的方式将该方法作为委托传递但不调用它,例如`Get <MyClass>(x => x.DoSomething)`,该怎么办? (2认同)