如何在 ASP.NET Core 中使控制器具有作用域或单例而不是瞬态?

问题描述 投票:0回答:2

如何在 ASP.NET Core 中使控制器具有作用域或单例而不是瞬态?

现在,默认情况下,控制器已注册到具有瞬态生命周期的默认 DI 容器。

如果我想为它们注册不同的生命周期,我该怎么做?

我想知道这只是出于教育目的,以便更好地了解 DI 容器的控制器类型管理。

asp.net-core dependency-injection controller transient
2个回答
33
投票

现在,默认情况下,控制器已注册到具有瞬态生命周期的默认 DI 容器。

默认情况下,控制器根本未注册。这是默认的 IControllerActivator

 在没有显式注册的情况下创建该类型。

如果您想更改此设置,请致电:

services.AddMvc().AddControllersAsServices();
这将确保控制器已注册,并且原始 

IControllerActivator

 被替换为从 DI 容器解析控制器的 (
ServiceBasedControllerActivator
)。
不幸的是,

AddControllersAsServices

始终使用 Transient 生活方式注册控制器,并且无法覆盖该行为。所以你必须重新实现
AddControllersAsServices
:

public static IMvcBuilder AddControllersAsServices( this IMvcBuilder builder, ServiceLifetime lifetime) { var feature = new ControllerFeature(); builder.PartManager.PopulateFeature(feature); foreach (var controller in feature.Controllers.Select(c => c.AsType())) { builder.Services.Add( ServiceDescriptor.Describe(controller, controller, lifetime)); } builder.Services.Replace(ServiceDescriptor .Transient<IControllerActivator, ServiceBasedControllerActivator>()); return builder; }
这个新的扩展方法可以使用如下:

services.AddMvc().AddControllersAsServices(ServiceLifetime.Singleton);

警告:不要将控制器注册为Singleton,以防它们派生自

Controller
ControllerBase
,因为这些类包含状态(正如@MarcoPelegrini在评论中正确指出的那样),并且在被重用时会出现故障多个请求。

    


0
投票

services.AddSingleton<MySingletonController>();

之前:

services.AddMvc().AddControllersAsServices();

它工作得很好,因为 
AddControllersAsServices

使用

builder.Services.TryAddTransient
。然后它不会将
MySingletonController
注册为瞬态,因为它已经在单例生命周期下完成了。
并且,如上所述,不要从 

MySingletonController

Controller
派生
ControllerBase
,因为它应该是无状态的。
    

© www.soinside.com 2019 - 2024. All rights reserved.