Create Expression> dynamically

2020-08-05 10:40发布

问题:

Related To: Create a Lambda Expression With 3 conditions

Please consider this GroupBy statement:

group r by new { r.EmployeeID, r.Name }

If I want to write above GroupBy statement with Lambda version and pass Expression<Func<T, TKey>> to it as parameter, How I can create Expression<Func<T, TKey>>?

回答1:

I don't have time to walk you through the whole thing, but the general gist is that you'll construct expressions using static methods off of the Expression class.

For example, the new expression will be created by passing constructor information and a series of expressions and such to one of the Expression.New() overloads.

The concept of r => ... is embodied by Expression.Lambda<Func<T, TKey>>(...) where you pass an Expression.Parameter(typeof(T), "r") as the lambda's parameter.

Expression.MakeMemberAccess will help you to produce r.EmployeeId and r.Name.

I find it useful to start by dumping a sample expression in LINQPad with code like this:

void Main()
{
    DumpExp(r => new { r.EmployeeID, r.Name });
}

public void DumpExp<TKey>(Expression<Func<Foo, TKey>> expr)
{
    expr.Dump();
}

public class Foo
{
    public string EmployeeID;
    public string Name;
}

That will allow you to inspect the tree and understand what types of expressions make up the tree, and what the values of their properties are. Then you can try writing code to match.

Once you've got an Expression that you think will work, you can call Compile on it to produce a runnable function, which you can use to test its behavior on in-memory objects.

I'm guessing the anonymous type you've got there may be the most difficult part of the problem. If the target framework supports something like Tuples in its GroupBy statements, you will probably be better off using those instead.

There is an oldish project that was designed to enable you to run dynamic LINQ statements built by providing strings to LINQ-like methods. It's called "Dynamic LINQ", and it might suit your needs.

You might also find this library useful. It's supposed to help you build Expression trees with a more fluent syntax. However, it doesn't appear to be under active development.