【问题标题】:Get Method Name From Action从操作中获取方法名称
【发布时间】:2011-03-19 19:53:55
【问题描述】:

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

    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));
)

【问题讨论】:

  • 这是一个LINQ表达式,你认为应该报告什么?如果是DeviceCommand(() => (standard ? api.WriteConfig(config) : api.WriteExtendedConfig(config)));应该是什么@
  • 你是说不传递某种参数就不可能完成我想要的,因为它是一个 LINQ 表达式?
  • 不,只是指出仅仅因为您的示例很简单,一般问题并不是因为 Action 可能是各种各样的东西,包括任何合格的代码块。我可能不会记录调用,但只要确保在出现异常时包含堆栈跟踪即可。或者,如果您想跟踪调用,只需在每个方法中记录调用。

标签: c# c#-4.0


【解决方案1】:

是的,有:Action.Method.Name

但是,这仅在将 Action 参数作为方法组而不是 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(){}
}

【讨论】:

  • Action.Method.Name 正在返回 DeviceCommand() 包含的方法的匿名方法名称,而不是实际的 api 调用。例如,Action.Method.Name 返回 MyMethod 而不是 WriteConfig。我更新了我的示例用法以显示这一点。
  • @Aaron, @Robert:我刚刚对此进行了测试,它仅在将 Action 参数作为“方法组”而不是 lambda 表达式传递时才有效。对于后者,您需要 Aarons 方法来传递 Expression
【解决方案2】:

如果您对 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 的调用频率)。您必须确定在您的情况下,性能影响(以及这种方法的一般“hack”)是否值得。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多