使用正确的派生类型调用泛型方法

时间:2012-05-31 09:31:19

标签: c# generics inheritance

我有以下情况:

我有三个课程,我们称他们为ABC。它们的共同点是它们从相同的接口ISomeInterface继承,并且它们是使用Entity Framework映射到实体的类。

我有一个接收实现此接口的对象List的方法,但对象本身将是ABC的实例。

方法shell看起来像这样

public void MyMethod(List<ISomeInterface> entityList)
{
  foreach(var entity in entityList)
  {
    ProcessEntity(entity);
  }
}

现在,问题在于ProcessEntity方法。这是一个通用方法,需要根据类型或实体从数据库中检索匹配元素的表,所以它看起来像这样:

public void ProcessEntity<T>(T entity)
{
  using( var repository = new DbRepository())
  {
    var set = repository.Set<T>();
    ...
  }
}

问题是,var set = repository.Set<T>();行失败了,因为在这种情况下TISomeInterface,而不是实际类型(AB或{ {1}}),因此它给出了一个与给定类型无关的异常,这是可以理解的。

所以我的问题是:如何使用列表中对象的实际类型调用ProcessEntity,而不是它们实现的接口类型。

3 个答案:

答案 0 :(得分:14)

将实体传递给ProcessEntity时,您可以应用dynamic关键字。在这种情况下,将在运行时确定实际类型的实体。

public void MyMethod(List<ISomeInterface> entityList)
{
  foreach(var entity in entityList)
  {
    dynamic obj = entity;
    ProcessEntity(obj);
  }
}

答案 1 :(得分:2)

好吧,你可以做一个类似访问者的技巧并使用以下解决方法:

  1. Process(EntityProcessor ep)
  2. 中定义方法ISomeInterface
  3. A中实施ep.ProcessEntity<A>(this)BC中的方式相同)
  4. 而不是循环中的ProcessEntity(entity),只需致电entity.Process(this)
  5. (方法名称可能不是最干净的,但你应该明白这一点)

答案 2 :(得分:2)

您可以使用反射来获取泛型方法定义,然后调用它,例如:

var method = typeof(ClassContainingProcessEntity)
    .GetMethod(ProcessEntity)
    .MakeGenericMethod(entity.GetType);
method.Invoke(this, entity);

您可以按类型缓存方法,如果性能很关键,您可以使用某种委托工厂在运行时编译它。

或者您可以使用Visitor pattern