M Hilmi Koca M Hilmi Koca - 3 months ago 31
C# Question

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.Response
1[System.Collections.Generic.List
1[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.

Answer

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