动态地将IEnumerable转换为IQueryable或使用LINQ表达式动态调用AsQueryable

Mil*_*vic 8 c# linq dynamic

我正在动态创建LINQ查询,到目前为止我做得很好.

但我被困在我认为不会的地方.在构建该查询的某个点上,我需要访问实体的EnityCollection.像这样的东西:

Expression collection = Expression.Property(entity, typeof(EntityType).GetProperty("CollectionOfRelatedEntities"));
Run Code Online (Sandbox Code Playgroud)

然后,我会在该集合上调用"Where"LINQ方法:

MethodCallExpression AfterWhere = Expression.Call(
                        typeof(Queryable),
                        "Where",
                        new Type[] { typeof(RelatedEntity) },
                        collection,
                        Expression.Lambda<Func<RelatedEntity, bool>>(predicate, new ParameterExpression[] { paramOfRelatedEntity }));
Run Code Online (Sandbox Code Playgroud)

通常这会奏效.在这种情况下它不会因为集合是IEnumerable而我需要它是IQueryable以便"Where"工作.

我试过这个:

Expression.Convert(collection, typeof(IQueryable<RelatedEntity>);
Run Code Online (Sandbox Code Playgroud)

但它说无法转换,因为EntityCollection没有实现IQueryable.

我静态地使用AsQueryable来实现我在这里需要的东西,所以我尝试动态地模仿它:

Expression.Call(collection, typeof(EntityCollection<RelatedEntity>).GetMethod("AsQueryable"));
Run Code Online (Sandbox Code Playgroud)

但我得到null引用异常.我无法通过反思达到它.这个AsQueryable方法是扩展方法,它是静态的,在Queryable类中定义,所以我试过:

Expression.Call(collection, typeof(Queryable).GetMethod("AsQueryable", BindingFlags.Static)); 
Run Code Online (Sandbox Code Playgroud)

相同的结果:"值不能为空".

我在这里达到了极限,我的想法很新鲜.

所以,我问你:

如何动态地将IEnumerable转换为IQueryable?

Igo*_*sky 5

尝试以这种方式获取方法:

var method = typeof(Queryable).GetMethod(
    "AsQueryable",
    BindingFlags.Static | BindingFlags.Public, 
    null, 
    new [] { typeof(IEnumerable<RelatedEntity>)}, 
    null);
Run Code Online (Sandbox Code Playgroud)

然后,您应该能够构建对该方法的调用,如下所示:

Expression.Call(method, collection);
Run Code Online (Sandbox Code Playgroud)

您的代码的问题是BindingFlags使用起来很棘手.如果你指定任何BindingFlags - 比如BindingFlags.Static - 那么你必须明确说明你是否想要BindingFlags.Public或BindingFlags.NonPublic.

然后第二个问题是有两个AsQueryable方法 - 一个通用方法和一个非通用方法.提供类型参数数组可以解决这种歧义.