public class ServiceCodeController : ControllerBase {
// the red squiggly under IJobRepository is saying it's not convertible
private LazyRepo<IJobRepository> _domainRepo2;
}
public class LazyRepo<TRepo> where TRepo : IRepository<IDomainEntity> { ... }
public interface IJobRepository : IRepository<JobDomain>, IListRepository { ... }
public interface IRepository<T> : IRepositoryRead<T>,
IRepositoryCreate<T>,
IRepositoryDelete<T>,
IRepositoryUpdate<T>
where T : IDomainEntity { ... }
public class JobDomain : BaseDomainEntity { ... }
public abstract class BaseDomainEntity : IDomainEntity,
IDomainEntityModifiable,
IDomainEntityActivatable,
IDomainEntityNameable { ... }
我的想法是,LazyRepo使用实现IRepository
的来实现{em>实现IDomainEntity
的。正如您所看到的,IJobRepository
实现IRepository
,其JobDomain
从BaseDomainEntity
继承,最终实现IDomainEntity
。
为了我的钱,这个应该用于设置LazyRepo类。
有人可以向我解释为什么我会收到此错误吗? 类型&#39; IJobRepository&#39;不能用作类型参数&#39; TRepo&#39;通用类型或方法&#39; LazyRepo&#39;。来自&#39; IJobRepository&#39;没有隐式引用转换。到&#39; IRepository&#39;
答案 0 :(得分:3)
我认为这是contravariance
和covariance
的概念所在。
协变接口允许其方法返回比接口中指定的类型更多的派生类型。逆变接口允许其方法接受比接口中指定的类型少的派生类型的参数。
来源:https://msdn.microsoft.com/en-us/library/dd465120.aspx
您可以使用in
和out
关键字解决此问题:
public interface IRepository<out T> : ...
答案 1 :(得分:0)
试试这个:
public class ServiceCodeController : ControllerBase {
// the red squiggly under IJobRepository is saying it's not convertible
private LazyRepo<IJobRepository, JobDomain> _domainRepo2;
}
public class LazyRepo<TRepo, TDomain> where TRepo : IRepository<TDomain> where TDomain : IDomainEntity { }
通过将TDomain指定为约束到IDomainEntity的通用参数并将TRepo约束到TDomain的IRepository,您可以提供编译器将IJobRepository和JobDomain解析为LazyRepo的参数所需的所有信息。这提供了使用差异的替代方法。
问题必须处理IRepository<IDomainEntity>
!= IRepository<JobDomain>
这一事实。这是在SO上讨论的经典水果碗问题。但是,如果将通用参数替换为IDomainEntity,则可以完全限定TRepo for LazyRepo的运行时定义。
为了完整性,以下是编译代码的修改版本:
public class ControllerBase {}
public interface IDomainEntity {}
public interface IDomainEntityModifiable {}
public interface IDomainEntityActivatable {}
public interface IDomainEntityNameable {}
public interface IListRepository {}
public interface IRepositoryRead<out TDomain> where TDomain : IDomainEntity {}
public interface IRepositoryCreate<out TDomain> where TDomain : IDomainEntity {}
public interface IRepositoryDelete<out TDomain> where TDomain : IDomainEntity {}
public interface IRepositoryUpdate<out TDomain> where TDomain : IDomainEntity {}
public class ServiceCodeController : ControllerBase
{
private LazyRepo<IJobRepository, JobDomain> _domainRepo2;
}
public class LazyRepo<TRepo, TDomain> where TRepo : IRepository<TDomain> where TDomain : IDomainEntity { }
public interface IJobRepository : IRepository<JobDomain>, IListRepository { }
public interface IRepository<out T> : IRepositoryRead<T>,
IRepositoryCreate<T>,
IRepositoryDelete<T>,
IRepositoryUpdate<T>
where T : IDomainEntity { }
public class JobDomain : BaseDomainEntity { }
public abstract class BaseDomainEntity : IDomainEntity,
IDomainEntityModifiable,
IDomainEntityActivatable,
IDomainEntityNameable { }