Inheritance in interface with generics
I’m trying to migrate an application which has to read from various XML, each of them having different models and methods/stuff to do before persisting them into db. For that reason, I’ve decided to create an interface IEntityController<T> where T : PersistentEntity
and a controller implementing it for each entity (XML), this way they all can have different implementations…
public interface IEntityController<T> where T : PersistentEntity { /// <summary> /// Check if the data inserted into the xml is valid and all the requirements are met /// </summary> /// <exception cref="FooValidationException">When the instance is not valid and can't be saved</exception> void Validate(T entity); /// <summary> /// Implement changes in data before its saved /// </summary> void PreProcess(T entity); /// <summary> /// Save or Update the entity /// </summary> /// <exception cref="System.Data.SqlClient.SqlException"></exception> void Persist(T entity); /// <summary> /// Implement changes in data after the entity is saved /// </summary> void PostProcess(T entity); }
After that, I’ve got a factory method which returns the proper controller based on the xml:
private IEntityController<PersistentEntity> GetController(XmlFile file) { Type fileType = file.GetType(); if(fileType == typeof(FileBoo)) return (IEntityController<PersistentEntity>) new BooController(DC); ...... }
My problem is: BooController
implements the interface of IEntityController<Boo>
where Boo
inherits PersistentEntity
, when trying to cast the controller to IEntityController<PersistentEntity>
I get an InvalidCastException
, though I have no problems casting BooController to IEntityController<Boo>
, It’s like C# ignores inheritance of the generic types.
Any ideas on how to solve this/implement it better? Thanks
The simplest thing you can do is to remove the generic type from IEntityController so that it looks like this:
public interface IEntityController { /// <summary> /// Check if the data inserted into the xml is valid and all the requirements are met /// </summary> /// <exception cref="FooValidationException">When the instance is not valid and can't be saved</exception> void Validate(PersistentEntity entity); /// <summary> /// Implement changes in data before its saved /// </summary> void PreProcess(PersistentEntity entity); /// <summary> /// Save or Update the entity /// </summary> /// <exception cref="System.Data.SqlClient.SqlException"></exception> void Persist(PersistentEntity entity); /// <summary> /// Implement changes in data after the entity is saved /// </summary> void PostProcess(PersistentEntity entity); }
Since your method
private IEntityController<PersistentEntity> GetController(XmlFile file)
always returns an IEntityController of PersistentEntity and not an IEntityController of T you don’t need generics at all.
Remember:
List<string> doesn't inherit from List<object>
otherwise this could happen
public static void DestroyTheWorld(List<object> list) { list.add(new object()); } public static void Main() { var list = new List<string>(); DestroyTheWorld(list); //possible if list<string> inherits from list<object> //an object has been added to a list of string }