Autofac ASP.NET Core 集成
ASP.NET Core(以前称为 ASP.NET 5)改变了以前的依赖注入框架如何集成到 ASP.NET 执行中。以前,每个功能(如 MVC、Web API 等)都有自己的 “依赖解析器” 机制,只是稍微不同的集成方式。ASP.NET Core 引入了符合规范的容器机制,通过 Microsoft.Extensions.DependencyInjection
,包括统一的请求生命周期范围、服务注册等功能。
此外,从 ASP.NET Core 3.0 开始,有一个通用的应用托管机制,可用于非 ASP.NET Core 应用。
此页面解释了 ASP.NET Core 和通用.NET Core 托管的集成。 如果您正在使用 ASP.NET 经典,请参阅 ASP.NET 经典集成页面 。
如果您使用的是 .NET Core 但不使用 ASP.NET Core(或不使用通用托管),则可以查看 此处有一个更简单的示例 ,展示这种集成。
快速入门
- 从 NuGet 引用
Autofac.Extensions.DependencyInjection
包。 - 在
Program.Main
方法中,将托管机制附加到 Autofac。(参见下面的示例。) - 在
Startup
类的ConfigureServices
方法中,使用其他库提供的扩展方法向IServiceCollection
注册内容。 - 在
Startup
类的ConfigureContainer
方法中,直接向 Autofac 的ContainerBuilder
注册内容。
IServiceProvider
会自动为您创建,您只需进行注册即可。
ASP.NET Core 1.1 - 2.2
这个示例展示了ASP.NET Core 1.1 - 2.2的用法,您在 WebHostBuilder
上调用 services.AddAutofac()
。**这不是用于 ASP.NET Core 3+**或.NET Core 3+的通用托管支持——ASP.NET Core 3 要求您直接指定服务提供者工厂,而不是将其添加到服务集合中。
这个示例展示了ASP.NET Core 1.1 - 2.2的用法,您从 ConfigureServices(IServiceCollection services)
委托中返回一个 IServiceProvider
。**这不是用于 ASP.NET Core 3+**或.NET Core 3+的通用托管支持——ASP.NET Core 3 已弃用从 ConfigureServices
返回服务提供者的功能。
ASP.NET Core 3.0+和通用托管
**在 ASP.NET Core 3.0 中,托管方式发生了变化,需要不同的集成。**您不能再从 ConfigureServices
返回 IServiceProvider
,也不能将服务提供者工厂添加到服务集合中。
这是针对 ASP.NET Core 3+和.NET Core 3+的通用托管支持:
Startup 类
在您的 Startup 类(适用于所有 ASP.NET Core 版本)中,然后使用 ConfigureContainer
访问 Autofac 的 ContainerBuilder 并直接向 Autofac 注册内容。
配置方法命名约定
Configure
、ConfigureServices
和 ConfigureContainer
方法都支持基于 IHostingEnvironment.EnvironmentName
的环境特定命名约定。默认情况下,名称分别为 Configure
、 ConfigureServices
和 ConfigureContainer
。如果您想要环境特定的设置,可以在 Configure
部分后面加上环境名,如 ConfigureDevelopment
、 ConfigureDevelopmentServices
和 ConfigureDevelopmentContainer
。如果没有匹配环境的方法,则使用默认方法。
这意味着您不一定需要使用 Autofac 配置 来在开发和生产环境中切换配置;您可以通过 Startup
中的程序性设置来实现。
这是 ASP.NET Core 应用程序主持的一项功能 - 它不是 Autofac 的行为。在 ASP.NET Core 中,启动过程是由 StartupLoader 类 负责定位需要调用的方法的。如果你想更深入地了解这是如何工作的,可以查看那个类。
依赖注入钩子
与 ASP.NET 经典集成 不同,ASP.NET Core 是专门为依赖注入设计的。这意味着如果你试图了解如何将服务注入到 MVC 视图( 这里 有更多说明),现在这些都由 ASP.NET Core 控制并文档化了,你只需要按照上面的说明设置你的服务提供者,而无需做任何特定于 Autofac 的操作。
以下是一些有关 ASP.NET Core 集成的链接,它们提供了关于 DI 整合的特定见解:
- ASP.NET Core 依赖注入基础
- 控制器注入
- ASP.NET Core MVC 中控制器依赖注入的微妙危险
- 过滤器注入
- 视图注入
- 授权需求处理器注入
- 中间件选项注入
- 中间件 "Invoke" 方法注入
- 使用 ASP.NET 将 EF 6 配置为服务
从 ASP.NET 经典迁移时的主要差异
如果你已经使用过其他 ASP.NET 集成 ,你可能会对迁移 ASP.NET Core 时的关键差异感兴趣。
- 使用 InstancePerLifetimeScope 替代 InstancePerRequest。 在以前的 ASP.NET 集成中,你可以将依赖项注册为
InstancePerRequest
,这将确保每个 HTTP 请求只创建一个依赖项实例。这之所以可行,是因为 Autofac 负责设置 “每个请求的生命周期作用域” 。随着Microsoft.Extensions.DependencyInjection
的引入,创建每个请求和其他子生命周期作用域现在是框架提供的符合规范的容器的一部分,因此所有子生命周期作用域都被平等对待 - 没有特殊的“请求级别作用域”。相反,你应该将依赖项注册为InstancePerLifetimeScope
,而不是InstancePerRequest
,以获得相同的行为。请注意,如果你在 Web 请求期间创建自己的生命周期作用域,那么在这些子作用域中会得到一个新的实例。 - 不再有 DependencyResolver。 其他 ASP.NET 集成机制需要在多个位置设置基于 Autofac 的自定义依赖注入解析器。现在通过
Microsoft.Extensions.DependencyInjection
和Startup.ConfigureServices
方法,只需返回IServiceProvider
,即可实现“魔法”。在控制器、类等中,如果需要手动进行服务定位,请获取IServiceProvider
。 - 没有特殊的中间件。 在以前的
OWIN 集成 <owin>
中,需要注册一个特殊的 Autofac 中间件来管理请求生命周期。现在Microsoft.Extensions.DependencyInjection
承担了繁重的工作,所以无需额外的中间件进行注册。 - 不再需要手动注册控制器。 以前,为了使 DI 工作,你需要将所有控制器注册到 Autofac 中。现在 ASP.NET Core 框架会自动将所有控制器通过服务解析,所以你不再需要这样做。
- 不再需要通过依赖注入扩展来调用中间件。 在
OWIN 集成 <owin>
中,有诸如UseAutofacMiddleware()
的扩展,允许将 DI 引入到中间件。现在,通过组合自动注入构造参数和动态解析到中间件的Invoke
方法的参数,这一切都自动完成。ASP.NET Core 框架处理所有这些。 - MVC 和 Web API 是一回事。 以前,根据你是使用 MVC 还是 Web API,会有不同的方式来接入 DI。在 ASP.NET Core 中,这两个东西合并在一起,所以只需要设置一个依赖注入解析器,维护一个配置文件即可。
- 控制器不会从容器中解析;只有控制器构造函数参数会被解析。 这意味着控制器生命周期、属性注入和其他事情都不会由 Autofac 管理,而是由 ASP.NET Core 管理。你可以使用
AddControllersAsServices()
来改变这一点,下面会详细讨论。
控制器作为服务
默认情况下,ASP.NET Core 会从容器解析控制器的 参数,但并不会实际从容器中解析 控制器本身。这通常不是问题,但它意味着:
- 控制器 的生命周期由框架而非请求生命周期管理。
- 控制器构造函数参数 的生命周期由请求生命周期管理。
- 你可能在注册控制器时做的特殊绑定(如设置属性注入)将不起作用。
要更改这一点,当您使用服务集合注册 MVC 时,可以指定 AddControllersAsServices()
。这样当服务提供者工厂调用 builder.Populate(services)
时,将自动将控制器类型注册到 IServiceCollection
中。
有关更详细的教程,包括步行游览,请参阅 Filip Woj 博客上的文章。那里的一位评论者还发现了一些关于 RC2 如何处理控制器作为服务的更改 见此处 。
多租户支持
由于 ASP.NET Core 对生成请求生命周期作用域的急切性,它使得多租户支持无法直接工作。有时用于租户识别的常见 IHttpContextAccessor
也可能来不及设置。为此,添加了名为 Autofac.AspNetCore.Multitenant
的包来修复这个问题。
启用多租户支持:
- 添加对
Autofac.AspNetCore.Multitenant
包的引用。 - 在
Program.Main
中创建 Web 主机时,包含一个调用UseServiceProviderFactory
扩展,并使用AutofacMultitenantServiceProviderFactory
。提供一个回调,用于配置您的租户。 - 在
Startup.ConfigureServices
和Startup.ConfigureContainer
中,注册那些不会特定于租户的东西,这些属于 根容器。 - 在回调(例如
Startup.ConfigureMultitenantContainer
)中构建多租户容器。
以下是 Program.Main
中的部分示例代码:
Startup
类的结构如下:
使用子作用域作为根
在复杂应用中,你可能希望将服务划分开来,让根容器在整个应用程序的不同部分之间共享,但使用托管部分(如 ASP.NET Core)的子生存期上下文。例如:
标准 ASP.NET Core 集成和通用托管应用程序支持中,你可以使用 AutofacChildLifetimeScopeServiceProviderFactory
替换标准 AutofacServiceProviderFactory
。这允许你在特定命名生存期上下文中附加配置操作,而不是构建好的容器。
这将改变你的 Startup
类的工作方式 - 你不再直接在 ConfigureContainer
中使用 ContainerBuilder
,现在它是 AutofacChildLifetimeScopeConfigurationAdapter
:
如果你不使用服务提供程序工厂,Populate()
方法提供了一个重载,允许你指定应作为"容器"使用的带有标签的子生存期上下文。
.NET Core集成文档还展示了使用子生存期上下文作为根的示例 。
使用子生存期上下文作为根与多租户支持不兼容。你必须选择一个,不能两者兼得。
示例
在 Autofac 示例存储库 中有一个演示 ASP.NET Core 集成的示例项目。