C# 我需要在Simple Injector中注册具体的根类型吗?

C# 我需要在Simple Injector中注册具体的根类型吗?,c#,dependency-injection,simple-injector,C#,Dependency Injection,Simple Injector,阅读简单的注入器文档,了解它是如何工作的,我阅读了下面的段落。除了粗体部分,我理解它的解释。这是什么意思 通过围绕构造函数注入模式设计应用程序中的类型,可以实现将这种依赖关系保持在最小的技术:在该类型的单个公共构造函数中定义类的所有依赖关系;对所有需要解析的服务类型执行此操作,仅直接解析应用程序中最顶层的类型(即,让容器为您构建依赖对象的完整图形) 我忽略了我对上面这句话的理解,但在尝试为WebAPI设置简单的注入器时,遇到了这行代码container.registerWebApp控制器(Glo

阅读简单的注入器文档,了解它是如何工作的,我阅读了下面的段落。除了粗体部分,我理解它的解释。这是什么意思

通过围绕构造函数注入模式设计应用程序中的类型,可以实现将这种依赖关系保持在最小的技术:在该类型的单个公共构造函数中定义类的所有依赖关系;对所有需要解析的服务类型执行此操作,仅直接解析应用程序中最顶层的类型(即,让容器为您构建依赖对象的完整图形)

我忽略了我对上面这句话的理解,但在尝试为WebAPI设置简单的注入器时,遇到了这行代码
container.registerWebApp控制器(GlobalConfiguration.Configuration)与此解释一致

因为控制器是具体的类,所以容器将能够在不进行任何注册的情况下创建它们


这是否意味着如果我有一堆不依赖于接口的类,我可以使用一行代码创建它们?(如果是这样,我应该怎么做)。

这意味着一种良好的做法,即不依赖代码中的DI容器,而只依赖于一些顶层,您必须这样做才能“启动”应用程序

这意味着您的所有类都将只具有接口形式的构造函数依赖项,而不会执行Container.Resolve。这将仅在应用程序的顶层调用

在某些框架中,您甚至不必自己去做,因为这是框架运行方式的一部分。据我所知,在.Net core中,例如,您不需要进行解析,但当控制器启动时,解析将在框架内发生

因为控制器是具体的类,所以容器可以 创建它们而不进行任何注册

这意味着您不必在容器中注册控制器本身。容器将只解析控制器依赖项本身,创建控制器并传递其中所有已解析的依赖项

注意:仅在应用程序的根目录中进行解析对于
SimpleInjector
来说并没有什么特殊性。这是一个很好的实践,可以应用于任何容器,并且即使您不遵循它,也可以使用
SimpleInjector
,这可能是目前没有人推荐的

对所有需要解析的服务类型执行此操作,并仅直接解析应用程序中最顶层的类型

这意味着,一旦您单独使用构造函数注入作为类获取其依赖关系的一种方式,您将最终构建可能有很多层的对象图。以这个对象图为例:

new HomeController(
    new ProductService(
        new SqlProductRepository(
            new CommerceContext(connectionString)),
        new AspNetUserContextAdapter(
            httpContextAccessor)));
PRO提示:您知道可以让Simple Injector在调试器中为您可视化对象图吗?这是可以解释的

在这里,您可以看到
HomeController
有一个依赖项(
IPProductService
),它通过其构造函数获得该依赖项
ProductService
本身有两个依赖项(
IPProductRepository
IUserContext
),它们也通过其构造函数提供。这可以深入到很多层

将构造函数注入作为向类提供依赖项的唯一方法意味着不允许类通过调用
容器来请求它们本身。这是一个公认的反模式,称为。构造函数注入简化了类,并允许容器为您分析对象图并检测任何异常

并仅直接解析应用程序中最顶层的类型

当使用构造函数注入构建整个对象图时,这意味着您只需请求
HomeController
,这是图中最顶层的类型。没有任何东西依赖于家庭控制器
<代码>HomeController
依赖于一切(隐式)。所有应用程序行为都是通过这些最顶层的类型调用的。在MVC应用程序中,这些通常是控制器、HTTP处理程序和模块

因为控制器是具体的类,所以容器将能够在不进行任何注册的情况下创建它们

这种说法有点误导。是的,Simple Injector确实能够为您创建请求的具体类型,即使该类型未注册。但是,正如文档中所解释的,最好始终在容器中注册根类型。这确保了容器知道这些类型,并允许对这些类型进行分析和验证。当您调用
container.Verify()
时,不注册这些具体的根类型会给您错误的安全感
Verify
只能对其知道的注册进行验证。当一个未注册的具体类型被引用为依赖项时,容器仍然知道它,但这显然不适用于根类型,因为没有任何东西依赖于它们

警告:在简单喷油器v5中,此行为可能会改变。默认情况下,Simple Injector v5可能不允许解析具体的未注册根类型


<代码>这只会在应用程序的顶层调用一次。< /代码> -您可能需要考虑将其更改为<代码>。这只会在您的应用程序的顶层调用。如果将DI与多个扩展点A集成在一起,则可能不止一次发生。也就是说,
container.Resolve
不应该出现在构成的类/方法之外。是的,这是正确的,我们已经修复了它。虽然为了简单起见,我想我们可以说一次:)