Expression.Call on array with a custom function

52 Views Asked by At

I have a list of items, I want ,via expression, to filter out the items using my own custom function.

Something like this

return Items.Where(Foo)
private static bool Foo(Item item) { item.Name.Equals("...");

what i currently have

public static Expression BuildExpression(IList<Item> items) 
{
    Expression<Func<Item, bool>> expression = item => Foo(item);
    var method = (expression.Body as MethodCallExpression)?.Method;
    return Expression.Call(method, Expression.Constant(items.First());
}

this seems to work find and well for 1 item but i can't figure out how to change it to work for IList<Item>

P.s

Foo signature can be changed if needed

1

There are 1 best solutions below

8
Guru Stron On BEST ANSWER

In the nutshell you need to find the Enumerable.Where<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) method. For example:

// find the Enumerable.Where with 2 parameters using reflection
var where = typeof(Enumerable).GetMethod(nameof(Enumerable.Where), BindingFlags.Public | BindingFlags.Static, new[]
{
    typeof(IEnumerable<>).MakeGenericType(Type.MakeGenericMethodParameter(0)),
    typeof(Func<,>).MakeGenericType(Type.MakeGenericMethodParameter(0), typeof(bool))
});

// make generic Enumerable.Where<Item>
var whereItem = where.MakeGenericMethod(typeof(Item));

// sample data 
IList<Item> items = new List<Item> { new() };
// sample filter
var filter = (Item i) => true;

// create expression
var expr = Expression.Call(whereItem, Expression.Constant(items), Expression.Constant(filter));

// validate
var enumerable = Expression.Lambda<Func<IEnumerable<Item>>>(expr).Compile()();

[email protected]

[email protected] with .NET Framework 4.7.1, main change:

var where = typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static)
    .First(mi => mi.Name == "Where" 
          && mi.GetParameters().Length == 2);

P.S.

TBH I doubt that this would be very useful for you but without having full overview of the problem it is hard to tell.