C# 为什么我不能将混凝土浇铸到带有接口的模板上?

C# 为什么我不能将混凝土浇铸到带有接口的模板上?,c#,dependency-injection,asp.net-mvc-5,covariance,contravariance,C#,Dependency Injection,Asp.net Mvc 5,Covariance,Contravariance,我读过很多与此相关的问题,也许这是一个重复,但我仍然不能理解这个概念。从我所读到的内容来看,这是与 我有以下接口和类: public interface IBaseEntity public interface IRepository<T> where T : IBaseEntity public interface ITravelRequest : IBaseEntity public interface IUser : IBaseEntity public class Tra

我读过很多与此相关的问题,也许这是一个重复,但我仍然不能理解这个概念。从我所读到的内容来看,这是与

我有以下接口和类:

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
公共接口IBaseEntity
公共接口i位置,其中T:IBaseEntity
公共接口ITravelRequest:IBaseEntity
公共接口IUser:IBaseEntity
公共类TravelRequest:ITravelRequest
公共类用户:IUser
我有一个控制器:

public TravelRequestsController(IRepository<ITravelRequest> repository, IRepository<IUser> userRepositor)
public TravelRequestsController(IRepository存储库、IRepository userRepositor)
我试图通过如下方式创建存储库来注入存储库:

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

var controller = new TravelRequestsController(travelRequestRepository, userRepository);
var travelRequestRepository=新存储库(上下文);
var userRepository=新存储库(上下文);
var控制器=新的TravelRequestsController(travelRequestRepository、userRepository);
但我得到了这个错误:

Error   4   Argument 1: cannot convert from
DAL.Repository<Elite.Models.TravelRequest.TravelRequest>' to
DAL.IRepository<Elite.Models.TravelRequest.ITravelRequest>' 
错误4参数1:无法从转换
DAL.Repository'to
DAL.IRepository'
我怎样才能做到这一点

更新-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();
    }
公共接口i假设,其中T:IBaseEntity
{
IEnumerable AsQueryable();
IList GetAll();
IList-Find(表达式谓词);
T单(表达式谓词);
T SingleOrDefault(表达式谓词);
T-First(表达式谓词);
T GetById(int-id);
T Create();
无效添加(T实体);
无效删除(T实体);
无效更新(T实体);
作废保存();
}

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

比如说,
IRepository
有一个
插入(T请求)
方法
Repository
将此方法实现为
Insert(T请求)
,这意味着
Repository
具有
Insert(TravelRequest请求)
方法签名,但它没有
Insert(ITravelRequest请求)
签名。

若要消除错误,请使用
out
关键字声明接口

public interface IRepository<out T> where T : IBaseEntity
{}
公共接口i假设,其中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
    { }
static void Main(字符串[]args)
{
var travelRequestRepository=新存储库();
var userRepository=newrepository();
测试(travelRequestRepository、userRepository);
Console.ReadLine();
}
静态无效测试(IRepository存储库、IRepository userRepositor)
{
}
公共接口IBaseEntity{}
公共接口i位置,其中T:IBaseEntity
{}
公共类存储库:IRepository,其中T:IBaseEntity
{
}
公共接口ITravelRequest:IBaseEntity
{}
公共接口IUser:IBaseEntity
{}
公共类TravelRequest:ITravelRequest
{}
公共类用户:IUser
{ }

那么如何将泛型与接口一起使用呢。我需要使用moq进行测试。@Daniel:选项1:认识到
TravelRequest
应该是一个POCO,没有可变行为,因此不需要模拟。插入一个
IRepository
并完全删除
ITravelRequest
接口。选项2:为
Repository
提供第二个泛型类型,以表示它应该为其实现
IRepository
的类型。还有其他选择,但这取决于您的具体情况。您对
IUser
ITravelRequest
接口的意图是什么?您真的打算为该
IUser
界面提供不同的用户实现吗?不要忘记接口是用来抽象行为的。抽象数据是没有用的。我认为这两个接口是无用的。删除这些接口,你的问题就会消失。我拥有这些接口的主要原因是为了测试。你说得对,它们可能没用。我已经找到了解决问题的方法,但我想知道我最初打算做的事情是否可行。原始的IRepository接口必须是不变的,但不能是协变或逆变的。因为在C#中,如果要使接口的类型参数T协变,必须指定“out”参数修饰符。有了这个修饰符,它意味着在你的界面中T只能被输出。添加/删除/更新违反了这些限制。对于逆变式也一样,您必须指定'in'修饰符,但在这之后,您不能有像Single/First/GetById这样的方法。只能使用“in”或“out”,但不能同时使用两者。当
T
是协变的时,实
IRepository
接口具有无法使用的方法(
Add\Delete\Update
)。