【问题标题】:Dependency injecting an IEnumerable of generic abstract class依赖注入通用抽象类的 IEnumerable
【发布时间】:2020-11-04 15:44:45
【问题描述】:

我有多个扩展通用抽象基类的类:

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 方面遗漏了一些东西,非常感谢任何帮助!

【问题讨论】:

  • 你用的是什么容器?

标签: c# generics dependency-injection abstract-class dryioc


【解决方案1】:

欢迎来到covariance and contravariance 的世界。虽然 IEnumerable&lt;T&gt; 是协变的,但您的 Base&lt;T&gt; 类不是,因为类不能对它们应用任何方差。只有接口和委托可以。这意味着以下代码无法编译:

Base<BaseDetails> b = new A();

上面的这段代码是一个重要的练习,因为当涉及到泛型时,DI Containers 很容易使您误以为问题出在 DI Container 中。始终尝试通过在不使用 DI 容器的情况下手动连接对象图来重建问题。例如:

IEnumerable<Base<BaseDetails>> _baseClasses = new Base<BaseDetails>[]
{
    new A(), // <- compile error here
    new B(), // <- compile error here
};

同样,这段代码不会在 C# 中编译:

CS0029 无法将类型“A”隐式转换为“Base”

要完成这项工作,您必须将Base&lt;T&gt; 更改为接口并使其T 通用参数协变:

public interface Base<out T> { }

【讨论】:

  • 谢谢你,帮了很多忙,没有完全解决我的问题,但它确实解决了我问的问题!现在有更多关于这个主题的研究要做!
【解决方案2】:

类似这样的:

builder.RegisterMany(new[] { Assembly.Load(nameof(Program)) },
 type => type.IsGeneric && type.GetGenericTypeDefinition() == typeof(Base<>)));

【讨论】:

    猜你喜欢
    • 2021-09-01
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 2017-01-06
    • 1970-01-01
    相关资源
    最近更新 更多