0

I have a method that uses an expression to define its output:

public async Task<TOut>
    GetCustomerAsync<TOut>(
        int customerId,
        Expression<Func<Models.Customer, TOut>> map)
{
    return await _customerService.GetMappedSingleAsync(
        map,
        customer => customer.Id == customerId;
}

I then have a number of different static expression methods that I can pass into this method, for example:

public static class CustomerExpressions
{
    public static Expression<Func<Models.Customer, CustomerItemDto>>
        CustomerItemDtoExpression()
    {
        return customer => new CustomerItemDto
        {
            CustomerId = customer.Id,
            CustomerName = customer.Name
        };
    }
}

The main method can then be called like this:

var customer = await _customerUiService.GetCustomerAsync(
    id, CustomerExpressions.CustomerItemDtoExpression());

I would now like to use reflection to create the expression tree from the designated expression method, so I could select the required expression by name. Something like this:

var dtoName = "CustomerItemDto";
var methodName = dtoName + "Expression";
var classType = typeof(CustomerExpressions);
var method = classType.GetMethod(methodName);

var expressionTree = /* Create an expression tree from the method */

var customer = await _customerUiService
    .GetCustomerAsync(id, expressionTree);

In other words, how can I compile the expression tree from my method's MethodInfo?

Any help would be much appreciated.

Update

So I have now got a little further with the code thanks to the comments

var dtoName = "CustomerItemDto";
var methodName = dtoName + "Expression";
var classType = typeof(CustomerExpressions);
var method = classType.GetMethod(methodName);

var expressionTree = method.Invoke(null, null);

// The problem now is that expressionTree is returned as an object,
// when, in this example, it needs to be of type
// Expression<Func<Models.Customer, TOut>>

var customer = await _customerUiService
    .GetCustomerAsync(id, expressionTree);

The problem now is that expressionTree is returned as an object, when it needs to be of type Expression<Func<Models.Customer, TOut>> - in this particular case the return type of the method Expression<Func<Models.Customer, CustomerItemDto>>

Neilski
  • 4,385
  • 5
  • 41
  • 74
  • Just invoke it (method.Invoke(null))? It will return the desired expression – Evk Nov 09 '20 at 17:18
  • Thank you Evk, but this gives me a compiler error: Cannot resolve method 'Invoke(null)', candidates are: object? Invoke(object?, object?[]?) (in class MethodBase) object? Invoke(object?, System.Reflection.BindingFlags, System.Reflection.Binder?, object?[]?, System.Globalization.CultureInfo?) (in class MethodBase) – Neilski Nov 09 '20 at 17:33
  • If I invoke as method.Invoke(null,null), then that works but I then get the following error when I pass that expression to the main function: .GetCustomerAsync(int, Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. – Neilski Nov 09 '20 at 17:40
  • @Neilski, maybe you are looking for something like this? https://github.com/scottksmith95/LINQKit/pull/127 – Svyatoslav Danyliv Nov 09 '20 at 18:12
  • @SvyatoslavDanyliv - that is pretty much what I am trying to do, but my problem is how to build the generic expression tree and submit it as a parameter to the main method – Neilski Nov 09 '20 at 18:25
  • @Neilski, `var expressionTree = (Expression>)method.Invoke(null, null);` But later look closer at my solution from LINQKit PR. – Svyatoslav Danyliv Nov 09 '20 at 18:38
  • Thank you @SvyatoslavDanyliv, but I think my use case is a little different, as I want to get the method by reflection, having done that, when I invoke the method I can't cast it to a typed return as I don't know what that is (as Invoke() returns an object).. If I try and pass the invoked expression tree object, the compiler emits an error as it is not of the expected generic type. – Neilski Nov 09 '20 at 20:19
  • @Neilski, yes cases are different, but sometime people choose strange solutions ;) – Svyatoslav Danyliv Nov 09 '20 at 21:34
  • @SvyatoslavDanyliv - Ha ha, fair point :-) – Neilski Nov 10 '20 at 05:06

0 Answers0