Как реализовать SelectMany в System.Linq.Dynamic ExpressionParser

Я пытаюсь реализовать оператор SelectMany внутри синтаксического анализатора динамических выражений linq, чтобы я мог выполнить такой запрос:

Customers.Select("Orders.SelectMany(OrderItems)")

Так, чтобы это было эквивалентно запросу linq:

Customers.Select(cust => cust.Orders.SelectMany(ord => ord.OrderItems))

Я попытался добавить SelectMany в IEnumerableSignatures System.Linq.Dynamic.ExpressionParser, но похоже, что мне нужно сделать еще больше.

Я просмотрел этот проект codeplex, но ничего с ним не сделал: http://dynamiclinq.codeplex.com/ в частности, он не запускал мои старые запросы и не поддерживал выбор или выбор многих.

В конечном итоге я хотел бы использовать все перечисляемые операторы linq внутри динамического оператора linq.


person cwohlman    schedule 28.11.2013    source источник


Ответы (1)


Чтобы заставить SelectMany работать внутри динамических запросов linq, вы должны не только изменить IEnumerableSignatures, но и изменить метод ParseAggregate, чтобы передать определенный typeArgs для SelectMany, следующим образом:

    Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos)
    {
        ...
        Type[] typeArgs;
        if (signature.Name == "Min" || signature.Name == "Max")
        {
            typeArgs = new Type[] { elementType, args[0].Type };
        }
        else if(signature.Name == "Select")
        {
            typeArgs = new Type[] { elementType, Expression.Lambda(args[0], innerIt).Body.Type };
        } 
        else if(signature.Name == "SelectMany")
        {
            var type = Expression.Lambda(args[0], innerIt).Body.Type;
            var interfaces = type.GetInterfaces().Union(new[] { type });
            Type resultType = interfaces.Single(a => a.Name == typeof(IEnumerable<>).Name).GetGenericArguments()[0];
            typeArgs = new Type[] { elementType, resultType };
        }
        else
        {
            typeArgs = new Type[] { elementType };
        }
        ...
    }
person Vladimir    schedule 06.01.2014
comment
Спасибо, работает отлично, я также заметил, что вы добавили Select. Обратите внимание, что я должен был убедиться, что подпись SelectMany включает селектор объектов, т.е. void SelectMany (селектор объектов) - person cwohlman; 06.01.2014