我在其他post中找到了这个方法,我几乎明白发生了什么,除了第 4 行:
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);
}
为什么 IEnumerable<string>.Aggregate
接受 Expression
和一个 MemberExpression
?
Aggregate 的重载似乎都不匹配这个调用
既然我不知道那里发生了什么,你能解释一下吗?
最佳答案
Why does IEnumerable.Aggregate accepts an
Expression
and aMemberExpression
?
传递给 Aggregate
的第二个参数不是 MemberExpression
!仔细看!
Expression.PropertyOrField
不是一个属性。这是一种方法。由于末尾没有括号,所以您没有调用它。 Expression.PropertyOrField
这里代表一个方法组。
Expression.PropertyOrField
接受 Expression
和一个 string
并返回 MemberExpression
, 所以它可以用委托(delegate)类型 Func<Expression, string, MemberExpression>
表示.第一个参数的类型是 Expression
,所以你实际上是在调用:
Aggregate(Expression, Func<Expression, string, MemberExpression>)
这与 overload 的签名匹配的 Aggregate
:
public static TAccumulate Aggregate<TSource,TAccumulate> (
this System.Collections.Generic.IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate,TSource,TAccumulate> func);
TAccumulate
是Expression
和 TSource
是string
.
至于这条线在高层做什么,我相信你现在已经明白了。它转换字符串 memberPath
,它可能看起来像这样:
w.x.y.z
进入Expression
表示该表达式的对象。
关于c# - 为什么这个 Linq 方法接受表达式类型的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56078927/