2

I need to execute some chained methods using reflection.

What I´m trying to get is an IQueryable of a Entity Core DBContext Set of an unknown compile type:

var type = typeof(x);
this.DBContext.Set(type).AsQueryable();

Obviously, that code does not compile because Set is a generic Method where the type must be defined in compile time:

this.DBContext.Set<TUnknownType>().AsQueryable();

To solve that, I tried to execute the methods using reflection:

    MethodInfo dbSetMethod = typeof(DbContext).GetMethod(nameof(DbContext.Set));
    MethodInfo generic = dbSetMethod.MakeGenericMethod(property.DeclaringType);

    var asQueryableMethod = generic.ReturnType.GetMethod("AsQueryable");
    var result = asQueryableMethod.Invoke(this.DbContext, null);

But when I debug the code, I get a null in the line:

var asQueryableMethod = generic.ReturnType.GetMethod("AsQueryable");

Apparently, the dbContext.Set<TUnknownType>() does not have the AsQueryable method. That method is an extension method coming from Linq I guess.

What am I missing? Why is the method unavailable?

Andres
  • 2,729
  • 5
  • 29
  • 60
  • When you say _of a dynamic type_ what exactly do you mean? Late bound dynamic type, closed generic type, runtime only type? – JSteward Mar 07 '18 at 19:46
  • Why the downvote? Its a clear question. Dynamic type means an unknown type until runtime. – Andres Mar 07 '18 at 19:47
  • 5
    Possible duplicate of [How to call a generic extension method with reflection?](https://stackoverflow.com/questions/15927028/how-to-call-a-generic-extension-method-with-reflection) – pm100 Mar 07 '18 at 19:52

1 Answers1

3

That's right, DbSet<T> implements IQueryable<T>, which exposes AsQueryable<T>() extension method.

C# offers two ways to invoke an extension method - as an instance method, i.e.

this.DBContext.Set<UnknownType>().AsQueryable();

or as a static method, i.e.

Queryable.AsQueryable(this.DBContext.Set<UnknownType>());

Reflection APIs, on the other hand, support only the second approach, i.e. the static method way of obtaining and invoking the method. You should get MethodInfo for generic Queryable.AsQueryable, and pass it an appropriate generic type parameter to make a MethodInfo object suitable for invocation.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    To put it into other words: The first way is syntactic sugar, resolved by the compiler, for the second way. – thehennyy Mar 07 '18 at 20:30
  • Ok, I get it. I was trying, but how can I pass the dbSetGeneric method as a parameter to the Queryable.AsQueryable() method? I´ve been trying but can´t get it working. – Andres Mar 08 '18 at 15:53
  • @Andres Get method info for `Queryable.AsQueryable` with one argument. Call `MakeGenericMethod` on it, passing `property.DeclaringType` for the argument. You should be able to invoke the resultant `MethodInfo`. – Sergey Kalinichenko Mar 08 '18 at 15:59
  • @dasblinkenlight I already got the method like this: `MethodInfo asQueryableMethod = typeof(Queryable).GetMethods().Where(x => x.Name == "AsQueryable" && !x.IsGenericMethod).First();` But its argument is a generic method info. I need to create a methodinfo representing this: `Queryable.AsQueryable(this.DBContext.Set());`. How can I pass that `Set<>()` method as a parameter? – Andres Mar 08 '18 at 17:26