Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

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.

 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 :

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()). It doesn't go into the most specific extension method. Any ideas ?

like image 656
Christophe Gigax Avatar asked Jul 22 '15 09:07

Christophe Gigax


1 Answers

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. This means that the type of item has to be determined at compile-time, not runtime. So the AbstractTableReferentielEntity version of the extension method is used as that's the one tht matches the type at compile time.

like image 145
David Arno Avatar answered Oct 23 '22 03:10

David Arno