如何在System.Linq.Dynamic ExpressionParser中实现SelectMany

时间:2013-11-28 15:11:48

标签: c# dynamic-linq linq

我正在尝试在动态linq expresion解析器中实现SelectMany语句,这样我就可以像这样运行查询:

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

这样与linq查询无关:

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

我已经尝试将SelectMany添加到System.Linq.Dynamic.ExpressionParser的IEnumerableSignatures中,但看起来还有更多我需要做的事情。

我已经查看了这个codeplex项目,但没有得到它:http://dynamiclinq.codeplex.com/具体而言,它不会运行我的旧查询,并且不支持select或select many。

最终我想在动态linq语句中使用所有可发布的linq语句。

1 个答案:

答案 0 :(得分:3)

对于make SelectMany在动态linq查询中的工作,你不仅要修改IEnumerableSignatures,还要更改ParseAggregate方法,以便为SelectMany传递特定的typeArgs,这样:

    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 };
        }
        ...
    }