根据给定的类型实现泛型方法调用

时间:2015-01-08 15:11:00

标签: c# entity-framework generics late-binding

我有一些(非)通用函数显式分配给DbSet(使用 Entity Framework 6.1 ,但问题在某种意义上更通用):

//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);
}

我知道虽然DerivedEntity1DerivedEntity2延伸Entity,但Dbset<DerivedEntityX>不会延伸DbSet<Entity>

我想要做的是,基于泛型类型实现后期绑定之类的行为。我想将泛型类型放入非泛型变量中,然后调用BuildQuery方法(在编译时可见非泛型类型):

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

我的问题是,这会导致根据泛型类型调用BuildQuery方法还是会调用非泛型方法?在第二种情况下,有没有办法实现这种方法调用?

2 个答案:

答案 0 :(得分:1)

  

这会导致根据泛型类型调用BuildQuery方法还是会调用非泛型方法?

它将使用非泛型重载。

  

在第二种情况下,有没有办法实现这种方法调用?

您可以将变量键入dynamic,但结果也会为dynamic

您也可以使用反射来确定dbSetNonGeneric的类型,您想要使用的重载,以及在对象上调用该重载。

更新:由于动态查找无法找到扩展方法(link),因此应将这些方法用作常规静态方法,以便与dynamic结合使用。

答案 1 :(得分:0)

它将调用非泛型方法。原因很简单,扩展方法基于变量类型而不是运行时类型(派生类型)调用

根据@Servy的建议你可以使用反射,但我怀疑dynamic

如果您有扩展程序,dynamic关键字将无效。

要用反射调用,你必须做点工作。实际上当反射被使用时它不会是实例方法的一部分,但它就像你用来创建扩展方法的静态类的静态方法。

以下链接将帮助您获取该方法并使用反射调用。

Reflection to Identify Extension Methods