为什么我不能用接口将具体的泛型转换为参数

本文关键字:泛型 转换 参数 不能 接口 为什么 | 更新日期: 2023-09-27 18:12:29

我已经阅读了许多与此相关的问题,也许这是一个重复,但我仍然无法理解这个概念。据我所知,这与协方差和逆变有关。

我有这些接口和类:

public interface IBaseEntity
public interface IRepository<T> where T : IBaseEntity
public interface ITravelRequest : IBaseEntity
public interface IUser : IBaseEntity
public class TravelRequest : ITravelRequest
public class User:  IUser

我有这个控制器:

public TravelRequestsController(IRepository<ITravelRequest> repository, IRepository<IUser> userRepositor)

我试图通过这样创建它们来注入存储库:

var travelRequestRepository = new Repository<TravelRequest>(context);
var userRepository = new Repository<User>(context);
var controller = new TravelRequestsController(travelRequestRepository, userRepository);

但是我得到这个错误:

Error   4   Argument 1: cannot convert from
DAL.Repository<Elite.Models.TravelRequest.TravelRequest>' to
DAL.IRepository<Elite.Models.TravelRequest.ITravelRequest>' 

我怎样才能使它工作?

更新-完整的IRepository

 public interface IRepository<T> where T : IBaseEntity
    {
        IEnumerable<T> AsQueryable();
        IList<T> GetAll();
        IList<T> Find(Expression<Func<T, bool>> predicate);
        T Single(Expression<Func<T, bool>> predicate);
        T SingleOrDefault(Expression<Func<T,bool>> predicate);
        T First(Expression<Func<T, bool>> predicate);
        T GetById(int id);
        T Create();
        void Add(T entity);
        void Delete(T entity);
        void Update(T entity);
        void Save();
    }

我可以改变控制器的签名,但我的最终目标是用Moq之类的东西来测试它

为什么我不能用接口将具体的泛型转换为参数

假设IRepository<T>有一个Insert(T request)方法。Repository<T>Insert(T request)的方式实现此方法,即Repository<TravelRequest>具有Insert(TravelRequest request)方法签名,但不具有Insert(ITravelRequest request)签名。

为了避免错误,使用out关键字声明接口

public interface IRepository<out T> where T : IBaseEntity
{}

我成功地编译了下面的代码。

    static void Main(string[] args)
    {
        var travelRequestRepository = new Repository<TravelRequest>();
        var userRepository = new Repository<User>();
        test(travelRequestRepository,userRepository);
        Console.ReadLine();

    }
    static void test(IRepository<ITravelRequest> repository, IRepository<IUser> userRepositor)
    {
    }

    public interface IBaseEntity{}
    public interface IRepository<out T> where T : IBaseEntity
    {}
    public class Repository<T>:IRepository<T> where T:IBaseEntity
    {
    }
    public interface ITravelRequest : IBaseEntity
    {}
    public interface IUser : IBaseEntity
    {}
    public class TravelRequest : ITravelRequest
    {}
    public class User : IUser
    { }