Подтвердить что ты не робот

Получить имя метода из действия

Можно ли получить имя метода из действия? Я знаю, что всегда могу передать строку, но я надеялся на что-то более умное.

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

Ответ 1

Если ваши вызовы 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). Вам придется решить, стоит ли влиять на производительность (и общая "взломать" ишемию этого подхода) в вашей ситуации.

Ответ 2

Да есть: Action.Method.Name

Однако это работает только в том случае, если вы передаете параметр Action в качестве группы методов, а не как выражение лямбда:

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(){}
}