繁体   English   中英

带接口的扩展方法

[英]Extension methods with interface

假设我们有这个模型:

public abstract class AbstractTableReferentielEntity {}
public class EstimationTauxReussite : AbstractTableReferentielEntity { }

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

public static EntityItemViewModel ToEntityItem<T>(this T entity)
    where T : AbstractTableReferentielEntity {}

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

 public static EntityItemViewModel ToEntityItem(this EstimationTauxReussite entity) {}

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

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

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

它汇编。

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

原因是扩展方法是“语法糖”,即它们是编译技巧。 你的路线:

.Select(item => item.ToEntityItem())

由编译器有效地转换为:

.Select(item => StaticClassWithExtensionMethod.ToEntityItem(item))

然后变成了IL。 这意味着必须在编译时确定item的类型,而不是运行时。 因此,使用扩展方法的AbstractTableReferentielEntity版本,因为它是在编译时匹配类型的那个。

如果我可以访问AbstractTableReferentielEntityEstimationTauxReussite类的源代码,我会按照以下方式重新制作它们

  1. 将虚拟ToEntityItem方法添加到AbstractTableReferentielEntity类
  2. 在EstimationTauxReussite类中重写它
  3. 删除两种扩展方法

现在Select(item => item.ToEntityItem())应该选择方法取决于输入对象

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

GetAllActifEntityItem方法中,编译器只知道TAbstractTableReferentielEntity ,因此它基于此解析ToEntityItem方法。 它实际上将使用EstimationTauxReussiteT调用的事实是无关紧要的。

可能的解决方法是使ToEntityItem的虚拟成员方法AbstractTableReferentielEntity ,并且在覆盖它EstimationTauxReussite 这样,虚拟分派将按预期发生,并且将调用正确的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM