2011-03-19 70 views
19

是否可以从动作获取方法名称?我知道我总是可以传递一个字符串,但我希望有更聪明的东西。从动作获取方法名称

public bool DeviceCommand(Action apiCall) 
    { 
     //It would be nice to log the method name that was passed in 
     try 
     { 
      apiCall(); 
     } 
     catch (Exception exc) 
     { 
      LogException(exc); 
      return false; 
     }   

     return true; 
    } 

用法是这样的:

void MyMethod() 
(
    DeviceCommand(() => api.WriteConfig(config)); 
) 
+2

这是一个LINQ表达式,你认为应该报告什么?如果它是'DeviceCommand(()=>(standard?api.WriteConfig(config):api.WriteExtendedConfig(config)));' – tvanfosson 2011-03-19 20:01:57

+0

你是说如果不通过某种方式就无法完成我想要的东西的参数,因为它是一个LINQ表达式? – Robert 2011-03-19 20:58:31

+1

不,只是指出,仅仅因为你的例子很简单,一般的问题并不是因为Action可能是各种各样的东西,包括任何有资格的代码块。我可能会没有记录这个调用,但只要确保包含堆栈跟踪(如果有异常)。或者如果您想跟踪通话,只需在每种方法中记录通话。 – tvanfosson 2011-03-19 21:13:14

回答

18

如果您对DeviceCommand的调用是总是将成为形式

DeviceCommand(() => someObject.SomeMethod(parameters)); 

的,那么你可以修改DeviceCommand采取一种表达式树作为参数。这将让你深入到树以获得您想要的信息(在这种情况下,字符串“的someMethod”),然后编译树成一个委托并执行它:

public bool DeviceCommand(Expression<Action> apiCallExp) 
{ 
    var methodCallExp = (MethodCallExpression) apiCallExp.Body; 
    string methodName = methodCallExp.Method.Name; 
    // do whatever you want with methodName 

    Action apiCall = apiCallExp.Compile(); 
    try 
    { 
     apiCall(); 
    } 
    catch(Exception exc) 
    { 
     LogException(exc); 
     return false; 
    } 

    return true; 
} 

当然,建筑并且每次编译一个表达式树可能是一个主要的性能问题(或不是 - 它只取决于调用DeviceCommand的频率)。您必须决定在您的情况下性能影响(以及此方法的一般“破解”)是否值得。

15

是的,有:Action.Method.Name

但是,如果在动作参数传递的方法组这只作品,而不是作为一个lambda表达式:

class Program 
{ 
    static void SomeActionName(){} 

    static void Main(string[] args) 
    { 
     LogMethodName(() => SomeActionName()); // <Main>b__0 
     LogMethodName(SomeActionName); // SomeActionName 

     var instance = new SomeClass(); 
     LogMethodName(() => instance.SomeClassMethod());; // <Main>b__1 
     LogMethodName(instance.SomeClassMethod); // SomeClassMethod 


    } 

    private static void LogMethodName(Action action) 
    { 
     Console.WriteLine(action.Method.Name); 
    } 
} 

class SomeClass 
{ 
    public void SomeClassMethod(){} 
} 
+0

Action.Method.Name正在返回包含DeviceCommand()的方法的匿名方法名称,而不是实际的api调用。例如,Action.Method.Name返回MyMethod而不是WriteConfig。我更新了我的示例用法以显示此内容。 – Robert 2011-03-19 20:52:32

+0

@Aaron,@Robert:我刚刚测试过这个,它只有在您将Action参数作为“方法组”传递,而不是作为lambda表达式时才有效。对于后者,你需要Aarons的方式传递一个'Expression' – jeroenh 2011-03-19 21:01:49