如何使用Expression.Call将SelectMany添加到表达式树

时间:2012-01-09 14:18:38

标签: c# linq expression-trees iqueryable anonymous-types

我如何获得与以下结果相同的结果:

var q = db.TableA.AsQueryable();
var q1 = Queryable.SelectMany(q, a => a.TableB, (a, t) => new { a = a, t = t });
var q2 = Queryable.SelectMany(q1, a=> a.a.TableC, (a, t) = new { a = a, t = t });

通过Expression.Call:

创建表达式树
MethodCallExpression returnCallExpression = Expression.Call(
     typeof(Queryable),
     "SelectMany",
     new Type[] ??????,
     query.Expression,
     a => a.TableB,
     (a, t) => new { a = a, t = t });

我正在研究Expression.Call的其他重载,看看是否可以在不声明类型的情况下实现。

我的问题是SelectManys的数量是在运行时确定的,所以我不能只链接它们。每个SelectMany都会更改IQueryable的匿名类型,因此我无法在编译时知道类型。

非常感谢有关如何将n个SelectMany应用于IQueryable的任何想法。

1 个答案:

答案 0 :(得分:1)

你真的让lambda表达式“可用”,例如a => a.TableB,还是动态的?

你可以使用这样的东西(基于这个SO post):

public Type[] GetSelectManysAnonymousTypes<TSource, TCollection, TResult>(
        IQueryable<TSource> queryable,
        Expression<Func<TSource, IEnumerable<TCollection>>> collectionSelector,
        Expression<Func<TSource, TCollection, TResult>> resultSelector)
{
    return new [] {
        typeof(Expression<Func<TSource, IEnumerable<TCollection>>>),
        typeof(Expression<Func<TSource, TCollection, TResult>>) };
}

或者更复杂的东西可以让Type[]Expression[]表达式一起返回collectionSelector - 准备调用Expression.Call()。

我认为你面临的问题是,忘记匿名类型,如果你真的有一个动态的,未知数量的SelectMany()链接在一起,你不知道{{1}}参数lambda是什么样的。或者我可能会遗漏一些东西......