依赖项注入通用抽象的 IEnumerable class
Dependency injecting an IEnumerable of generic abstract class
我有多个 class 扩展通用抽象基础 class:
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> {}
一切正常,我正在努力解决的是用于注册通用抽象基础 class 的许多实现的依赖注入,所以我想要的是:
IEnumerable<Base<BaseDetails>> _baseClasses;
我试过这样 DI 但没有成功:
builder.RegisterMany(new[] { Assembly.Load(nameof(Program)) }, type => type.IsAssignableTo(typeof(Base<>)));
我觉得我在 DI 方面遗漏了一些东西,非常感谢任何帮助!
像这样:
builder.RegisterMany(new[] { Assembly.Load(nameof(Program)) },
type => type.IsGeneric && type.GetGenericTypeDefinition() == typeof(Base<>)));
欢迎来到 covariance and contravariance 的世界。虽然 IEnumerable<T>
是协变的,但您的 Base<T>
class 不是,因为 classes 不能对它们应用任何方差。只有接口和委托可以。这意味着以下代码无法编译:
Base<BaseDetails> b = new A();
上面这段代码是一个重要的练习,因为当涉及到泛型时,DI 容器很容易让你误以为问题出在 DI 容器中。始终尝试在不使用 DI 容器的情况下通过 hand-wiring 您的对象图来重建问题。例如:
IEnumerable<Base<BaseDetails>> _baseClasses = new Base<BaseDetails>[]
{
new A(), // <- compile error here
new B(), // <- compile error here
};
同样,此代码无法在 C# 中编译:
CS0029 Cannot implicitly convert type 'A' to 'Base'
要实现此功能,您必须将 Base<T>
更改为接口并使其 T
泛型参数协变:
public interface Base<out T> { }
我有多个 class 扩展通用抽象基础 class:
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> {}
一切正常,我正在努力解决的是用于注册通用抽象基础 class 的许多实现的依赖注入,所以我想要的是:
IEnumerable<Base<BaseDetails>> _baseClasses;
我试过这样 DI 但没有成功:
builder.RegisterMany(new[] { Assembly.Load(nameof(Program)) }, type => type.IsAssignableTo(typeof(Base<>)));
我觉得我在 DI 方面遗漏了一些东西,非常感谢任何帮助!
像这样:
builder.RegisterMany(new[] { Assembly.Load(nameof(Program)) },
type => type.IsGeneric && type.GetGenericTypeDefinition() == typeof(Base<>)));
欢迎来到 covariance and contravariance 的世界。虽然 IEnumerable<T>
是协变的,但您的 Base<T>
class 不是,因为 classes 不能对它们应用任何方差。只有接口和委托可以。这意味着以下代码无法编译:
Base<BaseDetails> b = new A();
上面这段代码是一个重要的练习,因为当涉及到泛型时,DI 容器很容易让你误以为问题出在 DI 容器中。始终尝试在不使用 DI 容器的情况下通过 hand-wiring 您的对象图来重建问题。例如:
IEnumerable<Base<BaseDetails>> _baseClasses = new Base<BaseDetails>[]
{
new A(), // <- compile error here
new B(), // <- compile error here
};
同样,此代码无法在 C# 中编译:
CS0029 Cannot implicitly convert type 'A' to 'Base'
要实现此功能,您必须将 Base<T>
更改为接口并使其 T
泛型参数协变:
public interface Base<out T> { }