【发布时间】:2014-09-01 11:49:53
【问题描述】:
我已经阅读了许多与此相关的问题,也许这是重复的,但我仍然无法理解这个概念。从我读到的内容来看,这与covariance and contravariance 有关。
我有这些接口和类:
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 之类的东西对其进行测试。
【问题讨论】:
-
您对
IUser和ITravelRequest接口的意图是什么?你真的打算为IUser接口使用不同的用户实现吗?不要忘记接口是用来抽象行为的。抽象数据没有用。我相信这两个接口是没用的。删除这些接口,您的问题就会消失。 -
我拥有这些的主要原因是为了测试。你是对的,它们可能没用。我找到了解决问题的方法,但我想知道我最初打算做的事情是否可行。
-
您的原始 IRepository 接口必须是不变的,但不能是协变或逆变的。因为在 C# 中,如果要使接口协变的类型参数 T,则必须指定 'out' 参数修饰符。使用该修饰符意味着只能在您的界面中输出 T 。添加/删除/更新违反了这些限制。逆变也一样,你必须指定'in'修饰符,但之后你不能有像 Single/First/GetById 这样的方法。您只能使用“in”或“out”,但不能同时使用。
标签: c# dependency-injection asp.net-mvc-5 covariance contravariance