从Action获取方法名称

时间:2011-03-19 19:53:56

标签: c# c#-4.0

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

    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 个答案:

答案 0 :(得分:21)

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

答案 1 :(得分:19)

是的,有: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(){}
}