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

Sas*_*iha 9 dependency-injection controller transient asp.net-core

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

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

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

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

Ste*_*ven 13

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

默认情况下,控制器注册在所有。默认情况下IControllerActivator,在没有显式注册的情况下创建该类型。

如果你想改变这个,你应该调用:

services.AddMvc().AddControllersAsServices();
Run Code Online (Sandbox Code Playgroud)

这将确保控制器已注册,并且原始控制器被IControllerActivator一个 ( ServiceBasedControllerActivator)替换,该控制器从 DI 容器解析控制器。

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;
}
Run Code Online (Sandbox Code Playgroud)

这种新的扩展方法可以如下使用:

services.AddMvc().AddControllersAsServices(ServiceLifetime.Singleton);
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果您的控制器保持状态,使其成为单例就会出现问题。例如,在.NET 3.1中,如果您从Controller / ControllerBase继承,我的理解是ViewData和其他字段是不应该共享的状态。 (3认同)