Как я могу оценить часть выражения, которая ссылается на параметр? - PullRequest
0 голосов
/ 24 февраля 2020

Я пишу метод, предназначенный для анализа выражения вызова метода и определения (1) вызываемого метода и (2) передаваемых аргументов. Я могу получить метод просто отлично, но у меня возникают проблемы при оценке выражений аргументов.

Вот код:

public static void InspectExpression(Expression<Action<Input>> expression)
{
    var memberExpression = expression.Body as MethodCallExpression;
    var methodName = memberExpression.Method.Name;
    Console.WriteLine("The expression calls the {0} method.", methodName);

    var argumentExpression = memberExpression.Arguments[0];
    var argumentLambda = Expression.Lambda<Func<string>>(argumentExpression);
    var compiled = argumentLambda.Compile();
    var argumentValue = compiled();

    Console.WriteLine("The expression would pass {0} as the first argument to {1}", argumentValue, methodName);
}

Я вызываю его с помощью следующего кода:

public class Input
{
    public string SomeProperty { get; set; }
}

public static void MethodName(string arg)
{
    //Doesn't matter what this does
}

public static void Main()
{
    InspectExpression( i => MethodName(i.SomeProperty) );
}

Однако это приводит к следующему исключению:

[System.InvalidOperationException: variable 'i' of type 'Input' referenced from scope '', but it is not defined]

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

Поэтому я попытался добавить ввод следующим образом:

public static void InspectExpression(Expression<Action<Input>> expression)
{
    var memberExpression = expression.Body as MethodCallExpression;
    var methodName = memberExpression.Method.Name;
    Console.WriteLine("The expression calls the {0} method.", methodName);

    var argumentExpression = memberExpression.Arguments[0];
    var argumentLambda = Expression.Lambda<Func<Input,string>>(argumentExpression);
    var compiled = argumentLambda.Compile();

    var sampleInput = new Input { SomeProperty = "Hello world" };
    var argumentValue = compiled(sampleInput);

    Console.WriteLine("The expression would pass {0} as the first argument to {1}", argumentValue, methodName);
}

Возникло исключение:

[System.ArgumentException: Incorrect number of parameters supplied for lambda declaration]

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

Дайте пример ввода, как я могу получить вычисленный аргумент для этого выражения?

Вот ссылка на скрипку на случай, если вы захотите ее попробовать или использовать его в качестве основы для примера решения.

1 Ответ

1 голос
/ 24 февраля 2020

Вам нужно будет передать набор параметров в вызов Expression.Lambda<...>() - вы должны иметь возможность использовать тот же набор параметров, что и исходный expression, поэтому измените определение argumentLambda на:

var argumentLambda = Expression.Lambda<Func<Input,string>>(argumentExpression, expression.Parameters);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...