有人能解释一下为什么不是这样吗;是否有效实施
本文关键字:是这样吗 是否 有效 为什么不 一下 能解释 | 更新日期: 2023-09-27 18:05:19
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采用实现 就我的钱而言,这个应该用于设置LazyRepo类。 有人能向我解释一下我为什么会犯这个错误吗类型"IJobRepository"不能用作泛型类型或方法"LazyRepo"中的类型参数"TRepo"。没有从"IJobRepository"到"IRepository"的隐式引用转换IRepository
的东西,采用实现IDomainEntity
的东西
我认为这就是contravariance
和covariance
概念的来源。
协变接口允许其方法返回比接口中指定的派生类型更多的派生类型。逆变接口允许其方法接受派生类型少于接口中指定的派生类型的参数。
来源:https://msdn.microsoft.com/en-us/library/dd465120.aspx
您可以使用in
和out
关键字修复此问题:
public interface IRepository<out T> : ...
(来源:https://msdn.microsoft.com/en-us/library/dd997386.aspx)
试试这个:
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的运行时定义限定为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 { }