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

Add Comment
1 Answer(s)

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 } 
Answered on July 16, 2020.
Add Comment

Your Answer

By posting your answer, you agree to the privacy policy and terms of service.