Проблема с параметром в Expression.Lambda () - PullRequest
2 голосов
/ 24 мая 2009

Обновление: это работает, я был глуп: (

у меня есть следующий метод расширения

public static string ExtMethod(this object self, object myparameter);

во время выполнения это называется разными способами, я думаю, что это все возможности:

Expression<Func<T, string>> expr = x => x.property.ExtMethod(5);
Expression<Func<T, string>> expr = x => x.property.ExtMethod(new object());
Expression<Func<T, string>> expr = x => x.property.ExtMethod(someMethod());
Expression<Func<T, string>> expr = x => x.property.ExtMethod(x.someMethod());
Expression<Func<T, string>> expr = x => x.property.ExtMethod(x.OtherProperty);

что мне нужно сделать, это оценить "myparameter", учитывая "expr" и "T"

из-за двух случаев, когда x используется в myparameter, я подумал, что мне нужно создать делегата в форме:

Expression<Func<T, object>> expr = x => [myparameter expression here]

я думал, что это сработает:

var extMethodExpr = expr.Body as MethodCallExpression;
var myparameterExpr = extMethodExpr.Arguments[1];

var myparam = Expression.Lambda(myparameterExpr, expr.Parameters).Compile().Invoke(someT)

но для выражений, которые не включают x, я получаю TargetParameterCountException: (

в этих случаях, если я сделаю:

var myparam = Expression.Lambda(myparameterExpr).Compile().Invoke(someT)

работает нормально.

Как мне это решить?

спасибо

Ответы [ 2 ]

6 голосов
/ 24 мая 2009

OK; докопался до этого; в строке:

var myparam = Expression.Lambda(myparameterExpr).Compile().Invoke(someT);

Если вы не пытались передать someT, это сработало бы для тех выражений, которые не включают x в аргументе; для тех, кто это делает, вам нужно указать лямбду включить параметр (тот же, что и в оригинальной лямбде) - просто с помощью:

var myparam = Expression.Lambda(myparameterExpr,
             outerLambda.Parameters[0]).Compile().Invoke(someT);

Вот некоторый рабочий код, который оценивает внутренний параметр (с учетом экземпляра типа аргумента); обратите внимание, что я использую параметр, даже если он не включает x - в противном случае, что он будет делать с экземпляром?

using System;
using System.Linq.Expressions;
using System.Reflection;
class Foo {
    public string Bar {get;set;}
    public int someMethod() { return 4; }
    public int OtherProperty { get { return 3; } }
}
static class Program
{
    static int someMethod() { return 3; }
    static void Main()
    {
        Foo foo = new Foo();
        Test<Foo>(x => x.Bar.ExtMethod(5), foo);
        Test<Foo>(x => x.Bar.ExtMethod(new object()), foo);
        Test<Foo>(x => x.Bar.ExtMethod(someMethod()), foo);
        Test<Foo>(x => x.Bar.ExtMethod(x.someMethod()), foo);
        Test<Foo>(x => x.Bar.ExtMethod(x.OtherProperty), foo);
    }
    static void Test<T>(Expression<Func<T, string>> expr, T instance)
    {
        if (expr.Body.NodeType != ExpressionType.Call)
        {
            throw new InvalidOperationException("Call expected");
        }
        var call = ((MethodCallExpression)expr.Body);
        if (call.Method != typeof(Program).GetMethod(
            "ExtMethod", BindingFlags.Static | BindingFlags.NonPublic))
        {
            throw new InvalidOperationException("ExtMethod expected");
        }
        // we know that ExtMethod has 2 args; pick myParameter (the 2nd);
        // then build an expression over arg, re-using our outer param
        var newLambda = Expression.Lambda<Func<T, object>>(
            call.Arguments[1], expr.Parameters[0]);

        // evaluate it and show the argument value
        object value = newLambda.Compile()(instance);
        Console.WriteLine(value);
    }
    static string ExtMethod(this object self, object myParameter) {
        return self.ToString();
    }
}
0 голосов
/ 24 мая 2009

Что делать, если вы проверяете expr.Parameters.Count и, если оно равно 0, вызываете без параметров?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...