0

I have some (non)generic functions explicitly assigned to a DbSet (using Entity Framework 6.1, but the question is more generic, in a sense):

//Non-generic type method
public static IQueryable BuildQuery(this DbSet dbSet)
{
  return dbSet;
}
//Generic base class elements method
public static IQueryable<Entity> BuildQuery(this DbSet<Entity> dbSet)
{
  return dbSet.Include(de1 => de1.NavigationPropertyBase);
}
//Derived class 1 elements method
public static IQueryable<DerivedEntity1> BuildQuery(this DbSet<DerivedEntity1> dbSet)
{
  return dbSet.Include(de1 => de1.NavigationPropertyX);
}
//Derived class 2 elements method
public static IQueryable<DerivedEntity2> BuildQuery(this DbSet<DerivedEntity2> dbSet)
{
  return dbSet.Include(de2 => de2.NavigationPropertyX).
               Include(de2 => de2.NavigationPropertyY);
}

I know that although DerivedEntity1 and DerivedEntity2 extend Entity, Dbset<DerivedEntityX> does not extend DbSet<Entity>.

What I want to do though, is achieve a late-binding like behavior, based on the generic type. I thought to put the generic-type into a non-generic variable, and then invoke the BuildQuery method (visible as it exists for the non-generic type at compile time):

//This compiles with no errors.
DbSet dbSetNonGeneric = dbSet; // dbSet is of DbSet<DerivedEntity1> type
var result = dbSetNonGeneric.BuildQuery();

My question is, will this lead to an invocation of the BuildQuery method according to the generic type or will it invoke the non-generic method? And in the second case, is there a way to achieve that kind of method invocation?

Nick Louloudakis
  • 5,856
  • 4
  • 41
  • 54

2 Answers2

1

will this lead to an invocation of the BuildQuery method according to the generic type or will it invoke the non-generic method?

It will use the non-generic overload.

And in the second case, is there a way to achieve that kind of method invocation?

You can type the variable as dynamic, but then the result will also be dynamic.

You could alternatively use reflection to determine the type of dbSetNonGeneric, the overload you want to use, and to invoke that overload on the object.

UPDATE: Because dynamic lookup is not able to find extension methods (link), those should be used as normal static methods in order to work in combination with dynamic.

Community
  • 1
  • 1
Servy
  • 202,030
  • 26
  • 332
  • 449
  • Can you please give an example of the use of `dynamic` and/or the reflection use? Thank you. – Nick Louloudakis Jan 08 '15 at 15:38
  • @NickL. Try it and see what happens. If you have problems changing the type of a variable to `dynamic` then describe the specific problem that you're having. – Servy Jan 08 '15 at 15:39
  • The `dynamic` keyword was not very helpful, as the combination with extension methods is problematic in C# right now. Your answer helped me though, thank you very much. – Nick Louloudakis Jan 08 '15 at 17:58
  • @NickL. There's no reason you cannot use `dynamic` here. It's *dramatically* faster than using reflection and does exactly the same thing. – Servy Jan 08 '15 at 18:01
  • The invocation of extension methods using the dynamic keyword is not supported in C#, at least this is what I found searching. Please post a counter example of this, it is open to discussion for me. – Nick Louloudakis Jan 08 '15 at 18:12
  • @NickL. You cannot use the instance-like syntax, but at the end of the day it's still a static method just like any other, and can be called as such, and `dynamic` works just fine when calling a regular static method. – Servy Jan 08 '15 at 18:14
  • You are right about the use of `dynamic` in combination with extension methods as normal static ones. I updated your answer. Please take a look and accept it if you judge so. – Nick Louloudakis Jan 09 '15 at 13:27
0

It is going to call the non-generic method. Reason for this is simple, that extension methods call based on the type of variable rather than runtime type (derived type)

As per suggestion from @Servy you can use reflection but I have doubt about dynamic.

The dynamic keyword will not work when you have extension methods.

To call with reflection you have to do bit work. Actually when reflection get used It will not part of instance method but it will be like static method of static class that you have used to create extension method.

The following link will help you get that method and call using reflection.

Reflection to Identify Extension Methods

Community
  • 1
  • 1
dotnetstep
  • 17,065
  • 5
  • 54
  • 72
  • You are right about `dynamic`, I ended up using reflection, and that link was a treasure. Thank you! – Nick Louloudakis Jan 08 '15 at 18:00
  • @NickL. Dynamic works just fine with these methods, you simply cannot use the extension method syntax; using reflection is a ton of unnecessary busywork. – Servy Jan 08 '15 at 18:01
  • I am not sure why downvote but dynamic does not work with extension method and in question there is use of extension method. – dotnetstep Jan 09 '15 at 01:32
  • Well, `dynamic` can work if you use extension methods as normal static methods, doing a direct invocation of the static method and passing your object as the first argument. – Nick Louloudakis Jan 09 '15 at 13:28
  • That is what I am talking about and that is why I suggested to use reflection. – dotnetstep Jan 09 '15 at 15:11