[英]Extension methods with interface
Assume we have this model : 假设我们有这个模型:
public abstract class AbstractTableReferentielEntity {}
public class EstimationTauxReussite : AbstractTableReferentielEntity { }
I created a extension method for all classes that inherit from AbstractTableReferentielEntity. 我为从AbstractTableReferentielEntity继承的所有类创建了一个扩展方法。
public static EntityItemViewModel ToEntityItem<T>(this T entity)
where T : AbstractTableReferentielEntity {}
But for one specific type of AbstractTableReferentielEntity (like EstimationTauxReussite), I would like to perform a specific action, so I created a second extension method. 但对于一种特定类型的AbstractTableReferentielEntity(如EstimationTauxReussite),我想执行一个特定的操作,所以我创建了第二个扩展方法。
public static EntityItemViewModel ToEntityItem(this EstimationTauxReussite entity) {}
All extensions methods are declared in the same namespace. 所有扩展方法都在同一名称空间中声明。
After that, I retrieve some data from a DB with Entity Framework : 之后,我从具有Entity Framework的数据库中检索一些数据:
protected List<EntityItemViewModel> GetAllActifEntityItem<T>()
where T : AbstractTableReferentielEntity
{
return Context
.Set<T>()
.Where(item => item.IsActif)
.Select(item => item.ToEntityItem())
.ToList();
}
It compiles. 它汇编。
When T at runtime is a EstimationTauxReussite type, it goes into the wrong method ToEntityItem
when I call Select(item => item.ToEntityItem())
. 当运行时的T是EstimationTauxReussite类型时,当我调用Select(item => item.ToEntityItem())
时,它会进入错误的方法ToEntityItem
。 It doesn't go into the most specific extension method. 它没有进入最具体的扩展方法。 Any ideas ? 有任何想法吗 ?
The reason is that extension methods are "syntactic sugar", ie they are a compiler trick. 原因是扩展方法是“语法糖”,即它们是编译技巧。 Your line: 你的路线:
.Select(item => item.ToEntityItem())
is effectively converted by the compiler to: 由编译器有效地转换为:
.Select(item => StaticClassWithExtensionMethod.ToEntityItem(item))
and then turned into IL. 然后变成了IL。 This means that the type of item
has to be determined at compile-time, not runtime. 这意味着必须在编译时确定item
的类型,而不是运行时。 So the AbstractTableReferentielEntity
version of the extension method is used as that's the one tht matches the type at compile time. 因此,使用扩展方法的AbstractTableReferentielEntity
版本,因为它是在编译时匹配类型的那个。
If i have access to sources of AbstractTableReferentielEntity
and EstimationTauxReussite
classes i would remake them in following way 如果我可以访问AbstractTableReferentielEntity
和EstimationTauxReussite
类的源代码,我会按照以下方式重新制作它们
Now Select(item => item.ToEntityItem())
should pick method depends on input object 现在Select(item => item.ToEntityItem())
应该选择方法取决于输入对象
That's because extension methods are just syntactic sugar for static methods. 那是因为扩展方法只是静态方法的语法糖。 The method to call is resolved at compile time based on the compile-time type of the argument, there is no virtual dispatch involved. 调用方法在编译时根据参数的编译时类型解析,不涉及虚拟调度。
In your GetAllActifEntityItem
method, the compiler only knows that T
is a AbstractTableReferentielEntity
, so it resolves the ToEntityItem
method based on that. 在GetAllActifEntityItem
方法中,编译器只知道T
是AbstractTableReferentielEntity
,因此它基于此解析ToEntityItem
方法。 The fact that it will actually be called with EstimationTauxReussite
for T
is irrelevant. 它实际上将使用EstimationTauxReussite
为T
调用的事实是无关紧要的。
A possible workaround would be to make ToEntityItem
a virtual member method of AbstractTableReferentielEntity
, and override it in EstimationTauxReussite
. 可能的解决方法是使ToEntityItem
的虚拟成员方法AbstractTableReferentielEntity
,并且在覆盖它EstimationTauxReussite
。 This way, virtual dispatch will occur as expected and the correct method will be called. 这样,虚拟分派将按预期发生,并且将调用正确的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.