问题描述
我有多个类扩展了通用抽象基类:
public class BaseDetails {}
public class ADetails : BaseDetails {}
public class BDetails : BaseDetails {}
public abstract class Base<T> {}
public class A : Base<ADetails> {}
public class B : Base<BDetails> {}
这一切正常,我正在努力的是依赖注入,用于注册通用抽象基类的许多实现,所以我想要的是:
IEnumerable<Base<BaseDetails>> _baseClasses;
我试图像这样去DI,但是没有运气:
builder.RegisterMany(new[] { Assembly.Load(nameof(Program)) },type => type.IsAssignableto(typeof(Base<>)));
我觉得我在DI方面缺少一些东西,非常感谢您的帮助!
解决方法
欢迎来到covariance and contravariance的世界。尽管IEnumerable<T>
是协变的,但您的Base<T>
类却不是,因为类不能应用任何变化。只有接口和委托可以。这意味着以下代码无法编译:
Base<BaseDetails> b = new A();
上面的代码是一个重要的练习,因为涉及泛型时,DI容器很容易使您误以为问题出在DI容器中。始终尝试在不使用DI容器的情况下通过手动连接对象图来重建问题。例如:
IEnumerable<Base<BaseDetails>> _baseClasses = new Base<BaseDetails>[]
{
new A(),// <- compile error here
new B(),// <- compile error here
};
同样,此代码不会在C#中编译:
CS0029无法将类型“ A”隐式转换为“基本”
要执行此操作,必须将Base<T>
更改为接口,并使它的T
通用参数为协变量:
public interface Base<out T> { }
,
类似这样的东西:
builder.RegisterMany(new[] { Assembly.Load(nameof(Program)) },type => type.IsGeneric && type.GetGenericTypeDefinition() == typeof(Base<>)));