我正在动态创建 LINQ 查询,到目前为止一切正常。
但我被困在了我认为不会的地方。在构建该查询的某个时刻,我需要访问实体的 EnityCollection。像这样:
Expression collection = Expression.Property(entity, typeof(EntityType).GetProperty("CollectionOfRelatedEntities"));
然后,我将对该集合调用“Where”LINQ 方法:
MethodCallExpression AfterWhere = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { typeof(RelatedEntity) },
collection,
Expression.Lambda<Func<RelatedEntity, bool>>(predicate, new ParameterExpression[] { paramOfRelatedEntity }));
通常这会奏效。在这种情况下,它不会因为集合是 IEnumerable 并且我需要它是 IQueryable 才能在“Where”工作。
我试过这个:
Expression.Convert(collection, typeof(IQueryable<RelatedEntity>);
但它说无法转换,因为 EntityCollection 没有实现 IQueryable。
我静态地使用 AsQueryable 来实现我在这里需要的东西,所以我尝试动态地模仿它:
Expression.Call(collection, typeof(EntityCollection<RelatedEntity>).GetMethod("AsQueryable"));
但是我得到空引用异常。我无法通过反射到达它。这个 AsQueryable 方法是扩展方法,它是静态的,在 Queryable 类中定义,所以我尝试了:
Expression.Call(collection, typeof(Queryable).GetMethod("AsQueryable", BindingFlags.Static));
相同的结果:“值不能为空”。
我在这里达到了我的极限,我的想法很新鲜。
所以,我问你:
如何将 IEnumerable 动态转换为 IQueryable?
最佳答案
尝试这样获取方法:
var method = typeof(Queryable).GetMethod(
"AsQueryable",
BindingFlags.Static | BindingFlags.Public,
null,
new [] { typeof(IEnumerable<RelatedEntity>)},
null);
然后,您应该能够像这样构建对该方法的调用:
Expression.Call(method, collection);
您的代码存在的问题是 BindingFlags 很难使用。如果您指定任何 BindingFlags(例如 BindingFlags.Static),那么您还必须明确说明您是想要 BindingFlags.Public 还是 BindingFlags.NonPublic。
那么第二个问题是有两个 AsQueryable 方法——一个通用的和一个非通用的。提供类型参数数组可以解决这种歧义。
关于c# - 将 IEnumerable 动态转换为 IQueryable 或使用 LINQ 表达式动态调用 AsQueryable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9337125/