2

I found this method in other post, and I pretty much understand what's going on, except for the 4th line:

public static IQueryable<T> OrderByMember<T>(this IQueryable<T> source, string memberPath)
{
    var expression = source.Expression;

    var parameter = Expression.Parameter(source.ElementType, "x");

    string[] paths = memberPath.Split('.');

    /*****************HERE*******************/

    var member = paths.Aggregate((Expression)parameter, Expression.PropertyOrField);

    /****************************************/




    var selector = Expression.Lambda(member, parameter);
    var orderByCall = Expression.Call(typeof(Queryable), "OrderBy",
        new Type[] { parameter.Type, member.Type },
        expression, Expression.Quote(selector));
    return source.Provider.CreateQuery<T>(orderByCall);
}

Why does IEnumerable<string>.Aggregate accepts an Expression and a MemberExpression?

None of the overloads of Aggregate seem to match this call

https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.aggregate?view=netframework-4.6.2

Since I don't have a clue what's hapenning there, could you please explain?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
The One
  • 4,560
  • 5
  • 36
  • 52
  • So the arrays implement IQueryable? – The One May 10 '19 at 13:46
  • 1
    Oops! I brainfarted. The `parameter` is the seed, and the `PropertyOrField` is the accumulator. It is calling this [overload](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.aggregate?view=netframework-4.6.2#System_Linq_Enumerable_Aggregate__2_System_Collections_Generic_IEnumerable___0____1_System_Func___1___0___1__) – Sweeper May 10 '19 at 13:53

1 Answers1

1

Why does IEnumerable.Aggregate accepts an Expression and a MemberExpression?

The second argument passed to Aggregate is not a MemberExpression! Look carefully!

Expression.PropertyOrField is not a property. It is a method. Since there are no brackets at the end, you are not calling it. Expression.PropertyOrField represents a method group here.

Expression.PropertyOrField accepts an Expression and a string and returns a MemberExpression, so it can be represented by the delegate type Func<Expression, string, MemberExpression>. And the first argument is of type Expression, so you are essentially calling:

Aggregate(Expression, Func<Expression, string, MemberExpression>)

This matches the signature of this overload of Aggregate:

public static TAccumulate Aggregate<TSource,TAccumulate> (
    this System.Collections.Generic.IEnumerable<TSource> source, 
    TAccumulate seed, 
    Func<TAccumulate,TSource,TAccumulate> func);

TAccumulate is Expression and TSource is string.

As for what this line is doing on a high-level, well, I'm sure you've figured out by now. It converts the string memberPath, which might look something like this:

w.x.y.z

into an Expression object that represents that expression.

Sweeper
  • 213,210
  • 22
  • 193
  • 313