有人能解释一下为什么不是这样吗;是否有效实施

本文关键字:是这样吗 是否 有效 为什么不 一下 能解释 | 更新日期: 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采用实现IRepository的东西,采用实现IDomainEntity的东西

就我的钱而言,这个应该用于设置LazyRepo类。

有人能向我解释一下我为什么会犯这个错误吗类型"IJobRepository"不能用作泛型类型或方法"LazyRepo"中的类型参数"TRepo"。没有从"IJobRepository"到"IRepository"的隐式引用转换

有人能解释一下为什么不是这样吗;是否有效实施

我认为这就是contravariancecovariance概念的来源。

协变接口允许其方法返回比接口中指定的派生类型更多的派生类型。逆变接口允许其方法接受派生类型少于接口中指定的派生类型的参数。

来源:https://msdn.microsoft.com/en-us/library/dd465120.aspx

您可以使用inout关键字修复此问题:

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 {  }