Почему этот метод Linq принимает параметры типа Expression - PullRequest
2 голосов
/ 10 мая 2019

Я нашел этот метод в другом посте , и я довольно хорошо понимаю, что происходит, за исключением 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 и a MemberExpression?

Кажется, что ни одна из перегрузок Aggregate не соответствует этому вызову

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

Поскольку я понятия не имею, что там происходитне могли бы вы объяснить?

1 Ответ

1 голос
/ 10 мая 2019

Почему IEnumerable.Aggregate принимает Expression и MemberExpression?

Второй аргумент, передаваемый Aggregate, равен , а не a MemberExpression!Смотри внимательно!

Expression.PropertyOrField не является собственностью.Это метод.Поскольку в конце нет скобок, вы не называете это.Expression.PropertyOrField представляет здесь группу методов.

Expression.PropertyOrField принимает Expression и string и возвращает MemberExpression, поэтому он может быть представлен типом делегата Func<Expression, string, MemberExpression>.И первый аргумент имеет тип Expression, поэтому вы, по сути, звоните:

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

Это соответствует сигнатуре этой перегрузки из 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 объект, представляющий это выражение.

...