我在其他post中找到了这种方法,除了第四行外,我几乎了解发生了什么事:
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的重载似乎都不符合此调用
https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.aggregate?view=netframework-4.6.2
由于我不知道那里发生了什么,您能解释一下吗?
答案 0 :(得分:1)
为什么IEnumerable.Aggregate接受
@forelse ($event->invitations as $event) <h5>{{ $event->email }}</h5> @empty <h5>Not Found</h5> @endforelse
和Expression
?
传递给MemberExpression
的第二个参数是 not 一个Aggregate
!仔细看!
Expression.PropertyOrField
不是属性。这是一种方法。由于末尾没有方括号,因此您无需调用它。 MemberExpression
在这里代表方法组。
Expression.PropertyOrField
接受一个Expression.PropertyOrField
和一个Expression
并返回一个string
,因此可以用委托类型MemberExpression
表示。第一个参数的类型为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
对象中。