Search code examples
c#genericsfactory-pattern

C# Factory Method with Generic Cast to Interface


I have the following classes:

// -- model hierarchy
public interface IJob {
}

public abstract class AbstractJob : IJob {
}

public class FullTimeJob : AbstractJob {               
}

// -- dao hierarchy
public interface IJobDao<T> where T : IJob {       
  T findById(long jobId);
  long insert(T job);
}

public interface IFullTimeJobDao : IJobDao<FullTimeJob> {        
}

public abstract class AbstractDao {    
}

public abstract class AbstractJobDaoImpl<T> : AbstractDao, IJobDao<T> where T : IJob {
  public T findById(long jobId) {
    // omitted for brevity
  }

  public long insert(T job) {
    // omitted for brevity
  }
}

public class FullTimeJobDaoImpl : AbstractJobDaoImpl<FullTimeJob>, IFullTimeJobDao {
}

I'm calling the following code from a factory method, which does not seem to work:

public IJobDao<IJob> createJobDao(long jobDaoTypeId)
{
    object jobDao = Activator.CreateInstance(typeof(FullTimeJobDaoImpl));
    return jobDao as IJobDao<IJob>; // <-- this returns null
    return (IJobDao<IJob>) jobDao; // <-- this cast fails
}

How is this "up cast" properly achieved?


Solution

  • For this cast to be possible you'll need to mark the interface type parameter as out:

    public interface IJobDao<out T> where T : IJob {...}
    

    Then

    object jobDao = Activator.CreateInstance(typeof(FullTimeJobDaoImpl));
    var r = jobDao as IJobDao<IJob>; //not null
    

    But this brings some restrictions on the interface. Read out (Generic Modifier) (C# Reference) for more info.

    In a generic interface, a type parameter can be declared covariant if it satisfies the following conditions:

    1. The type parameter is used only as a return type of interface methods and not used as a type of method arguments.
    2. The type parameter is not used as a generic constraint for the interface methods.