Search code examples
c#.netexpression-trees

Call method Expression Tree in C#


I want create expression with reflection in c#.

I am target script is:

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

How to (srv => srv.GetProducts() script is generate with expression tree?

Edit:

I am sorry for the wrong expression. wherein IProductsService, Response<List<Product>> and GetProducts are actually unknown types. I take generic on runtime.

I wrote the following methods(CreateExpression) to try. But Expression property = Expression.Call(methodReturnType, methodName.Name, new Type[]{ } ,parameter); line gives the following error:

No method 'GetProducts' exists on type 'ServiceFoundation.Response1[System.Collections.Generic.List1[ServiceFoundation.Products.Product]]'.

Next in line for I have not tested it yet.

Method:

private void CreateExpression(Type interfaceType, Type methodReturnType, MethodInfo methodName)
    {
    ParameterExpression parameter = Expression.Parameter(interfaceType, "srv");
    Expression property = Expression.Call(methodReturnType, methodName.Name, new Type[]{ } ,parameter);       
    Type expressionType = typeof(Expression<>);
    Type lambdaType = typeof(LambdaExpression);
    Type funcType = typeof(Func<,>);
    Type delegateType = funcType.MakeGenericType(interfaceType, methodReturnType);
    Type expression = expressionType.MakeGenericType(delegateType);

    MethodInfo mI = typeof(Expression).GetMethod("Lambda");
    MethodInfo lambda = mI.MakeGenericMethod(delegateType);
    var ex = lambda.Invoke(this, new object[] { delegateType, property, parameter });
}

Hopefully I can express.


Solution

  • I succeeded after a long struggle. I examined different questions here. and in the end I solved this way:

     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;
            }