Как определить параметры анонимной функции в C #? - PullRequest
3 голосов
/ 11 октября 2011

Учитывая следующий код,

    public T Execute<T>(Func<T> methodParam)
    {
        return methodParam ();
    }

    public void CallMethodsAnonymously<T>()
    {
        T result =  Execute(() => _service.SomeMethod1());
        T result1 = Execute(() => _service.SomeMethod2(someParm1));
        T result2 = Execute(() => _service.SomeMethod3( someParm1, someParm2));
    }

Можно ли из метода Execute проверить «methodParam» и извлечь или определить количество параметров в теле анонимной функции?Например, возможно ли определить значения someParam1 и someParam2 из метода Execute?

Ответы [ 4 ]

6 голосов
/ 11 октября 2011

Вы можете сделать это, используя Expression API:

public static T Execute<T>(Expression<Func<T>> methodParam)
{
    var methodCallExpression = methodParam.Body as MethodCallExpression;
    var method = methodCallExpression.Method;
    var parameters = method.GetParameters();

    return methodParam.Compile()();
}

Переменная параметров будет массивом ParameterInfo объектов, которые будут содержать необходимую информацию. Наконец, метод Compile фактически преобразует выражение в исполняемый делегат. Компилятор C # также позволяет вызывать этот метод с обычными соглашениями о вызове методов, которые принимают делегаты, со стандартными лямбда-выражениями / анонимными методами.

EDIT:

Я также только что заметил, что вы хотели получить фактическое значение для someParam1 и someParam2. Вот как вы можете это сделать:

private static object GetValue(Expression expression)
{
    var constantExpression = expression as ConstantExpression;
    if (constantExpression != null)
    {
        return constantExpression.Value;
    }

    var objectMember = Expression.Convert(expression, typeof(object));
    var getterLambda = Expression.Lambda<Func<object>>(objectMember);
    var getter = getterLambda.Compile();
    return getter();
}


private static object[] GetParameterValues(LambdaExpression expression)
{
    var methodCallExpression = expression.Body as MethodCallExpression;
    if (methodCallExpression != null)
    {
        return methodCallExpression.Arguments.Select(GetValue).ToArray();
    }

    return null;
}

Так что теперь в вашем методе execute, если вы сделаете это:

public static T Execute<T>(Expression<Func<T>> methodParam)
{
    var methodCallExpression = methodParam.Body as MethodCallExpression;
    var method = methodCallExpression.Method;
    var parameters = method.GetParameters();

    var values = GetParameterValues(methodParam);
    return methodParam.Compile()();
}

тогда значения будут объектом [] со всеми фактическими значениями, которые были переданы.

0 голосов
/ 17 июля 2012

Я не думаю, что это отвечает на вопрос вообще.Это фактически выполняет метод делегата и возвращает результаты в объект values ​​[].Я полагаю, что автор спрашивал, а также спрашиваю, как получить значения параметров в методе делегата.

0 голосов
/ 11 октября 2011

Это маловероятно. Методу Execute передается делегат - в этом случае ссылка на анонимную функцию. То, что вы просите, - это метод Execute, чтобы заглянуть внутрь кода этой функции и определить, что он делает.

Это все равно, что пытаться заглянуть внутрь метода Random.Next во время выполнения, чтобы увидеть, какие методы он вызывает.

0 голосов
/ 11 октября 2011

Ни в одном из вызовов methodParam нет параметров.
Код: () => _service.SomeMethod1() в основном «указывает» на другую функцию, которая возвращает T.
() => _service.SomeMethod1() эквивалентно:
() => { return _service.SomeMethod1(); }

Изменить, чтобы фактически ответить на вопрос (глупый я):
Попробуйте:

T result2 =
   Execute(() =>
   {
      [BreakPoint]return _service.SomeMethod3(someParm1, someParm2)
   }
);
...