Reputation: 810
I am using two types generic interface called IRepository<Entity, DTO>
. How can I initialize in RepositoryFactory by using Dependency Injection.
Interface that I try to initialize.
public interface IRepository<Entity, DTO> where Entity : BaseEntity where DTO : BaseDTO
{
bool Save(Entity Entity);
bool Save(Entity Entity, out int OutID);
bool Update(Entity Entity);
bool Update(Entity Entity, out int OutID);
DTO GetRecord(Entity ID);
DTO GetRecord(Expression<Func<Entity, bool>> predicate);
List<DTO> GetList();
List<DTO> GetByQuery(Expression<Func<Entity, bool>> predicate);
}
BaseEntity, BaseDTO
public abstract class BaseEntity
{
public int ID { get; protected set; }
}
public class BaseDTO
{
public int ID { get; protected set; }
}
AdministratorRepository
public class AdministratorRepository : Repository<AdministratorEntity, AdministratorDTO>
{
public AdministratorRepository(string ConnectionString) : base(ConnectionString)
{
}
// Implemented functions for Repository base class
}
Repository base repository class
public abstract class Repository<Entity, DTO> : IRepository<Entity, DTO>
where Entity : BaseEntity
where DTO : BaseDTO
{
// Implemented functions for IRepository Interface
}
RepositoryFactory
public class RepositoryFactory<Entity, DTO> where Entity : BaseEntity where DTO : BaseDTO
{
private static string CONNECTION_STRING = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
public static IRepository<Entity, DTO> Create(Repositories repository)
{
IRepository<Entity, DTO> iRepo = null;
switch (repository)
{
// If I do this, program wants me to cast
case Repositories.Administrator:
// Casting error occured in this line.
// AdministratorRepository derives from Repository.
/*
Cannot implicitly convert type
'BusinessRules.Repositories.AdministratorRepository' to
'BusinessRules.Repositories.IRepositories.IRepository<Entity,DTO>'.
An explicit conversion exists (are you missing a cast?)
*/
iRepo = new AdministratorRepository(CONNECTION_STRING);
break;
// If I do this, program throws an exception
// Exception: TypeInitializationException
// Exception Description: The type initializer for 'BusinessRules.Repositories.RepositoryFactory`2' threw an exception.
case Repo.Administrator:
iRepo = (IRepository<Entity, DTO>)(new AdministratorRepository(CONNECTION_STRING));
break;
}
return iRepo;
}
}
Upvotes: 3
Views: 923
Reputation: 10849
The scenario you have mentioned is "where you are trying to assign a more derived type object than to a generic type parameter of the interface". To allow the assignment, you should define the generic interface with out parameter type. Read this article to understand variance in C#.
You can declare a generic type parameter covariant by using the out keyword.
So define the IRepository
interface as
public interface IRepository<out Entity, out DTO> where Entity : BaseEntity where DTO : BaseDTO
{
//......
}
Full Code (sample app - Check this live fiddle)
using System;
public abstract class BaseEntity
{
public int ID { get; protected set; }
}
public class BaseDTO
{
public int ID { get; protected set; }
}
public interface IRepository<out Entity, out DTO> where Entity : BaseEntity where DTO : BaseDTO
{
string GetTestString();
}
public abstract class Repository<Entity, DTO> : IRepository<Entity, DTO>
where Entity : BaseEntity
where DTO : BaseDTO
{
// Implemented functions for IRepository Interface
public Repository(string connectionString)
{
}
public abstract string GetTestString();
}
public class AdministratorEntity : BaseEntity
{
}
public class AdministratorDTO : BaseDTO
{
}
public class AdministratorRepository : Repository<AdministratorEntity, AdministratorDTO>
{
public AdministratorRepository(string ConnectionString) : base(ConnectionString)
{
}
public override string GetTestString()
{
return "TestString";
}
// Implemented functions for Repository base class
}
public class Program
{
public static void Main()
{
IRepository<BaseEntity, BaseDTO> repo = new AdministratorRepository("connectionString");
Console.WriteLine(repo.GetTestString());
Console.WriteLine("Hello World");
}
}
Upvotes: 1