在C#中调用方法表达式树

时间:2016-09-02 07:18:43

标签: c# .net expression-trees

我希望在c#中使用反射创建表达式。

我的目标脚本是:

using (var service = new MyProxy<IProductsService>())
{
    var response = service.DoAction<Response<List<Product>>>(srv => srv.GetProducts());
}

如何使用表达式树生成(srv => srv.GetProducts()脚本?

修改

我很抱歉错误的表达。 其中IProductsService, Response<List<Product>>GetProducts实际上是未知类型。我在运行时采用泛型。

我写了下面的方法(CreateExpression)来试试。但是Expression property = Expression.Call(methodReturnType, methodName.Name, new Type[]{ } ,parameter);行会出现以下错误:

  

没有方法&#39; GetProducts&#39;存在于类型上   &#39; {ServiceFoundation.Response {1}} 1 [ServiceFoundation.Products.Product]]&#39;

接下来我还没有测试过。

方法:

1[System.Collections.Generic.List

希望我能表达。

2 个答案:

答案 0 :(得分:0)

如果你有

Expression<Action<Response>>

你可以打电话

.Compile()

就可以了,它会返回一个

Action<Response>

然后您可以正常调用。

例如

Expression<Action<Response>> exp = resp => Console.WriteLine(resp);
Action<Response> func = exp.Compile();
func(myResponse);

但是,如果您只需要这样做,您可能会发现根本不使用表达式会更简单;

Action<Response> func = resp => Console.WriteLine(resp);
func(myResponse);

答案 1 :(得分:0)

经过长时间的斗争,我取得了成功。我在这里研究了不同的问题 最后我解决了这个问题:

 private Expression CreateExpression(Type interfaceType, Type methodReturnType, MethodInfo methodName)
        {
            ParameterExpression parameter = Expression.Parameter(interfaceType, "srv");
            Expression callExpression = Expression.Call(parameter, methodName.Name,null, null);

            Type expressionType = typeof(Expression<>);
            Type lambdaType = typeof(LambdaExpression);
            Type funcType = typeof(Func<,>).MakeGenericType(interfaceType, methodReturnType);
            Type expressionGenericType = expressionType.MakeGenericType(funcType);

            string methodSignature = "System.Linq.Expressions.LambdaExpression Lambda(System.Linq.Expressions.Expression, System.Linq.Expressions.ParameterExpression[])";
            var lambdaMethod = typeof(Expression).GetMethods()
                .Single(mi => mi.ToString() == methodSignature);

            Expression lambdaExpression = (Expression)lambdaMethod.Invoke(this, new object[] { callExpression, new ParameterExpression[] { parameter } });
            return lambdaExpression;
        }