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
Since I don't have a clue what's hapenning there, could you please explain?
Why does IEnumerable.Aggregate accepts an
Expression
and aMemberExpression
?
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.