我正在尝试使用工厂解决策略模式。该工厂生成一个开放的通用接口。它取决于该通用接口的IEnumerable。我可以获得一个非通用的IEnumerable来工作,但是使用泛型我得到一个空列表。
我也可以直接解析该类,但不能解析该列表。
另一个警告是我们可能拥有可能无限的存储库,因此单独注册它们会很痛苦。
我已经尝试过这些方式注册Autofac
var dataAccess = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(dataAccess).AsClosedTypesOf(typeof(Repositories.IRepository<>));
builder.RegisterAssemblyTypes(dataAccess)
.Where(t => IsAssignableToGenericType(t, typeof(Repositories.IRepository<>)) && !t.IsAbstract && !t.IsInterface)
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(dataAccess)
.Where(t => IsAssignableToGenericType(t, typeof(Repositories.IRepository<>)) && !t.IsAbstract && !t.IsInterface);
public interface IRepository<T> where T : BaseProcessorType
{
Task Add(T data);
}
public abstract class BaseRepository<T> : IRepository<T> where T : BaseProcessorType
{
public async Task Add(T data)
{
// something
}
}
public class ActivityRepository : BaseRepository<Activity>, IRepository<Activity>
{
public ActivityRepository() : base()
{
}
public override async Task Add(Activity data)
{
// override
}
}
然后我想解决
var lol = something.Resolve<IEnumerable<Repositories.IRepository<BaseProcessorType>>>();
但不幸的是,这会返回一个空的IRepositories列表。
让我们忘记Autofac
,让我们试着用纯粹的C#来收集它
IEnumerable<IRepository<BaseProcessorType>> l = new IRepository<BaseProcessorType>[] {
new ActivityRepository()
};
使用代码示例编译器抛出错误
错误CS0266 - 无法将type
ActivityRepository
隐式转换为IRepository<BaseProcessorType>
。存在显式转换(您是否错过了演员?)
主要错误是ActivityRepository
不能转换为IRepository<BaseProcessorType>
。为了允许这个演员你必须使用T
关键字使out
参数协变
public interface IRepository<out T> where T : BaseProcessorType
{}
但通过这样做你不能有一个T
参数的方法
错误CS1961无效方差:类型参数
T
必须在IRepository<T>.Add(T)
上违反有效。T
是协变的。
要理解为什么禁止它,让我们看看这个代码示例:
IRepository<BaseProcessorType> r = new Activity1Repository();
r.Add(new Activity2());
在这个代码示例r
与Activity1
一起工作,但你想添加Activity2
和Activity1
不是Activity2
。
一种解决方案是不使用T
作为类型参数,而是使用BaseProcessorType
public interface IRepository<out T> where T : BaseProcessorType
{
Task Add(BaseProcessorType data);
}
这样纯C#解决方案就有效了。
要解决IEnumerable<IRepository<BaseProcessorType>>
,您需要将您的类型注册为IRepository<BaseProcessorType>
。
builder.RegisterAssemblyTypes(dataAccess)
.As(typeof(IRepository<BaseProcessorType>));