Dependency injection ASP.NET内核和ViceProvider

Dependency injection ASP.NET内核和ViceProvider,dependency-injection,asp.net-core,asp.net-core-mvc,Dependency Injection,Asp.net Core,Asp.net Core Mvc,所以,我一直在阅读CQR,同时决定我的项目的架构,并找到了库。它不是很复杂或类似的东西,但有一件事吸引了我的眼球:ISeviceProvider正在被注入并被使用。所以,我的问题是:直接与服务提供者构建对象是一种好的做法吗?也就是说,不使用注入?如果不知道,如果对象的类型只有在运行时才知道,那么哪种方法才是构建对象的正确方法?如果您只知道运行时的类型,那么使用IServiceProvider基本上是DI的唯一选项(例如,在MVC组件中通过RequestServices) 构造函数注入只有在编译时

所以,我一直在阅读CQR,同时决定我的项目的架构,并找到了库。它不是很复杂或类似的东西,但有一件事吸引了我的眼球:ISeviceProvider正在被注入并被使用。所以,我的问题是:直接与服务提供者构建对象是一种好的做法吗?也就是说,不使用注入?如果不知道,如果对象的类型只有在运行时才知道,那么哪种方法才是构建对象的正确方法?

如果您只知道运行时的类型,那么使用IServiceProvider基本上是DI的唯一选项(例如,在MVC组件中通过
RequestServices

构造函数注入只有在编译时已经知道类型时才可行,因为必须在构造函数中指定对象的类型

根据需要,您还可以在
ConfigureServices()
中注册实现工厂,并根据运行时信息给出某些接口的不同实例

编辑:ASP.NET核心中的实现工厂示例:

services.AddTransient<IDataService, DataService>((ctx) =>
{
    IOtherService svc = ctx.GetService<IOtherService>();
    //IOtherService svc = ctx.GetRequiredService<IOtherService>();
    return new DataService(svc);
});
services.AddTransient((ctx)=>
{
IOtherService svc=ctx.GetService();
//IOtherService svc=ctx.GetRequiredService();
返回新的数据服务(svc);
});

这里的
DataService
依赖于
IOtherService
,因此它通过
GetService()
从服务提供商处获得它。您可以使用
GetRequiredService()
来强制执行该要求。

如果您只知道运行时的类型,那么使用
IServiceProvider
基本上是DI的唯一选项(例如,通过MVC组件中的
RequestServices

构造函数注入只有在编译时已经知道类型时才可行,因为必须在构造函数中指定对象的类型

根据需要,您还可以在
ConfigureServices()
中注册实现工厂,并根据运行时信息给出某些接口的不同实例

编辑:ASP.NET核心中的实现工厂示例:

services.AddTransient<IDataService, DataService>((ctx) =>
{
    IOtherService svc = ctx.GetService<IOtherService>();
    //IOtherService svc = ctx.GetRequiredService<IOtherService>();
    return new DataService(svc);
});
services.AddTransient((ctx)=>
{
IOtherService svc=ctx.GetService();
//IOtherService svc=ctx.GetRequiredService();
返回新的数据服务(svc);
});
这里的
DataService
依赖于
IOtherService
,因此它通过
GetService()
从服务提供商处获得它。您可以使用
GetRequiredService()
强制执行该要求

直接使用服务提供者构建对象(也就是说不使用注入)是一种好的做法吗

视情况而定。将通用解析器注入到类中而不是特定的依赖项是一种通常被称为的模式,它被认为是

然而,此IServiceProvider的使用是否是服务定位器反模式的实现取决于其使用方式,如下所述:

封装在中的DI容器不是服务定位器,而是一个基础结构组件

我们可以认为这个代码>命令处理器< /C>是一个基础结构,只要它被“封装在一个组成根”中。

直接使用服务提供者构建对象(也就是说不使用注入)是一种好的做法吗

视情况而定。将通用解析器注入到类中而不是特定的依赖项是一种通常被称为的模式,它被认为是

然而,此IServiceProvider的使用是否是服务定位器反模式的实现取决于其使用方式,如下所述:

封装在中的DI容器不是服务定位器,而是一个基础结构组件


我们可以认为这个代码>命令处理器< /代码>是一个基础结构,只要它被封装在“组成根”中。

但<> >只有应用程序应该有组合根。库和框架不应该@arthur.borisow:没错。
CommandProcessor
应该是启动项目的一部分。您当然不应该将
ICommand
ICommandHandler
抽象和
CommandProcessor
实现放在同一个项目中。但是
只有应用程序才应该具有合成根。库和框架不应该
@arthur.borisow:没错。
CommandProcessor
应该是启动项目的一部分。您当然不应该将
ICommand
ICommandHandler
抽象和
CommandProcessor
实现放在同一个项目中。同意,但是,除非您手动创建依赖项,否则factory不允许您将任何内容注入到您构建的对象中,但这样您就失去了依赖项注入内置frameworkTrue的优势,尽管在factory中,您可以从容器请求依赖项,所以它不完全是手动的。您是什么意思?你能举个例子吗?您是说factory接收服务提供商还是我遗漏了什么?添加了一个示例:)同意,但factory不允许您将任何内容注入到您构建的对象中,除非您手动创建依赖项,但这样您就失去了依赖项注入内置框架的优势True,虽然在工厂中,您可以从容器中请求依赖项,所以它不完全是手动的。您是什么意思?你能举个例子吗?你是说工厂接收了服务提供商,还是我遗漏了什么?增加了一个例子:)