I am creating LINQ query dynamically, and I am doing OK so far.
But I am stuck where I thought I wouldn't be. At a certain point in building that query, I need to access EnityCollection of an entity. Something like this:
Expression collection = Expression.Property(entity, typeof(EntityType).GetProperty("CollectionOfRelatedEntities"));
Then, I would call "Where" LINQ method upon that collection:
MethodCallExpression AfterWhere = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { typeof(RelatedEntity) },
collection,
Expression.Lambda<Func<RelatedEntity, bool>>(predicate, new ParameterExpression[] { paramOfRelatedEntity }));
And normally that would work. In this case it won't because collection is IEnumerable and I need it to be IQueryable in order "Where" to work.
I tried this:
Expression.Convert(collection, typeof(IQueryable<RelatedEntity>);
but it says unable to cast because EntityCollection doesn't implement IQueryable.
I statically use AsQueryable to achieve what i need here, so i tried mimicking that dynamically:
Expression.Call(collection, typeof(EntityCollection<RelatedEntity>).GetMethod("AsQueryable"));
but I get null reference exception. I can't reach it via reflection. This AsQueryable method is extension method, it is static, defined in Queryable class, so i tried:
Expression.Call(collection, typeof(Queryable).GetMethod("AsQueryable", BindingFlags.Static));
Same result: "Value cannot be null".
I am reaching my limits here, and I am fresh out of ideas.
So, I am asking you:
How can I dynamically cast IEnumerable to IQueryable?
Try to get the method this way:
var method = typeof(Queryable).GetMethod(
"AsQueryable",
BindingFlags.Static | BindingFlags.Public,
null,
new [] { typeof(IEnumerable<RelatedEntity>)},
null);
Then, you should be able to construct a call to that method like this:
Expression.Call(method, collection);
The problem with your code was that BindingFlags are tricky to use. If you specify any BindingFlags - like BindingFlags.Static - then you also have to explicitly say whether you want BindingFlags.Public or BindingFlags.NonPublic.
Then the second problem is that there are two AsQueryable methods - a generic one and a non-generic one. Providing the array of type arguments resolves that ambiguity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With