带接口的扩展方法

Chr*_*gax 6 c# inheritance extension-methods

假设我们有这个模型:

public abstract class AbstractTableReferentielEntity {}
public class EstimationTauxReussite : AbstractTableReferentielEntity { }
Run Code Online (Sandbox Code Playgroud)

我为从AbstractTableReferentielEntity继承的所有类创建了一个扩展方法.

public static EntityItemViewModel ToEntityItem<T>(this T entity)
    where T : AbstractTableReferentielEntity {}
Run Code Online (Sandbox Code Playgroud)

但对于一种特定类型的AbstractTableReferentielEntity(如EstimationTauxReussite),我想执行一个特定的操作,所以我创建了第二个扩展方法.

 public static EntityItemViewModel ToEntityItem(this EstimationTauxReussite entity) {}
Run Code Online (Sandbox Code Playgroud)

所有扩展方法都在同一名称空间中声明.

之后,我从具有Entity Framework的数据库中检索一些数据:

protected List<EntityItemViewModel> GetAllActifEntityItem<T>()
    where T : AbstractTableReferentielEntity
{
    return Context
        .Set<T>()
        .Where(item => item.IsActif)
        .Select(item => item.ToEntityItem())
        .ToList();
}
Run Code Online (Sandbox Code Playgroud)

它汇编.

当运行时的T是EstimationTauxReussite类型时,它ToEntityItem在我调用时会进入错误的方法Select(item => item.ToEntityItem()).它没有进入最具体的扩展方法.有任何想法吗 ?

Tho*_*que 1

这是因为扩展方法只是静态方法的语法糖。要调用的方法是在编译时根据参数的编译时类型解析的,不涉及虚拟调度。

在您的GetAllActifEntityItem方法中,编译器只知道它T是 a AbstractTableReferentielEntity,因此它ToEntityItem根据它来解析该方法。事实上,它实际上会被EstimationTauxReussitefor调用T是无关紧要的。

一种可能的解决方法是创建 的ToEntityItem虚拟成员方法AbstractTableReferentielEntity,并在 中重写它EstimationTauxReussite。这样,虚拟调度将按预期发生,并且将调用正确的方法。