Adding a method call to a Linq expression, while remaining a complete expression

How do I extend a linq expression while preserving its expression? I simplified this quite a bit (to avoid inserting pages) -.eg I work with Queryable, not Enumerable, but there is enough solution for this, in the end I need to save it as an expression, adding a method call to it.

For example, L

        var p1 = new Person() {Name = "RDA1", Age = 27};
        var p2 = new Person() {Name = "RDA2", Age = 28};
        var p3 = new Person() {Name = "RDA3", Age = 29};

        var people = new[] {p1, p2, p3};


        Expression<Func<IEnumerable<Person>, IEnumerable<Person>>> filterExp
            = list => list.Take(2);


        Expression<Func<Person, int>> sortExp = l => l.Age;


        MethodCallExpression orderByCallExpression = Expression.Call(
            typeof (Enumerable),
            "OrderByDescending",
            new Type[] {typeof (Person), typeof (int)},
            filterExp.Parameters[0],
            sortExp); 

var combinedExpression = Expression.Lambda<Func<IEnumerable<Person>, IEnumerable<Person>>>
(filterExp.AddMethodCall(orderByCallExpression)); // made up AddMethodCall but you get the idea

I have searched for dozens of SO posts in the last few hours, and I cannot figure it out, I can do this if I compile filterExp, but not without expressing both expressions and the end result.

+1
source share
1 answer

-, IEnumerable: AsQueryable() :

var p1 = new Person() { Name = "RDA1", Age = 27 };
var p2 = new Person() { Name = "RDA2", Age = 28 };
var p3 = new Person() { Name = "RDA3", Age = 29 };

var people = new[] { p1, p2, p3 }.AsQueryable();

, , , :

Expression<Func<IQueryable<Person>, IQueryable<Person>>> filterExp
    = list => list.Take(2);

Expression<Func<Person, int>> sortExp = l => l.Age;

MethodCallExpression orderByCallExpression = Expression.Call(
    typeof(Queryable),
    "OrderByDescending",
    new Type[] { typeof(Person), typeof(int) },
    filterExp.Body,
    sortExp);

var combinedExpression =
    Expression.Lambda<Func<IQueryable<Person>, IQueryable<Person>>>(
        orderByCallExpression, filterExp.Parameters[0]);

filterExp.Body list.Take(2) OrderByDescending, filterExp .

, ?

var compiled = combinedExpression.Compile();
var res = compiled(people);

foreach (var r in res)
{
    // Do something
}
+3

Source: https://habr.com/ru/post/1543275/


All Articles