两种类型通用接口的依赖注入

时间:2018-06-08 10:46:32

标签: c# generics dependency-injection interface

我使用两种类型的通用接口IRepository<Entity, DTO>。如何使用依赖注入在RepositoryFactory中初始化。

我尝试初始化的

接口

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; }
}

管理员存储库

public class AdministratorRepository : Repository<AdministratorEntity, AdministratorDTO>
{
    public AdministratorRepository(string ConnectionString) : base(ConnectionString)
    {

    }

    // Implemented functions for Repository base 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;
    }
}

1 个答案:

答案 0 :(得分:0)

您提到的场景是“您尝试分配更多派生类型对象而不是接口的泛型类型参数”。要允许分配,您应该使用out参数类型定义通用接口。 阅读本文以了解C#中的variance

您可以使用out关键字声明泛型类型参数协变。

因此将IRepository接口定义为

public interface IRepository<out Entity, out DTO> where Entity : BaseEntity where DTO : BaseDTO
{
    //......
}

完整代码(示例应用 - 检查this实况小提琴)

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");
    }
}