IHttpControllerActivator 中的控制器处置

Controller disposal in IHttpControllerActivator

我有一个自定义 IHttpControllerActivator 用于我的网络 api 控制器,我将其与简单的注入器一起使用:

public sealed class ApiControllerActivator : IHttpControllerActivator
{
    private readonly Container _container;
    private readonly IHttpControllerActivator _original;

    public ApiControllerActivator(Container container, IHttpControllerActivator original)
    {
        _container = container;
        _original = original;
    }

    public IHttpController Create(HttpRequestMessage request,
                        HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        var controller = CreateController(request, controllerDescriptor, controllerType);
        // request.RegisterForDispose(...); required?
        return controller;
    }

    private IHttpController CreateController(HttpRequestMessage request, 
                        HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        if (controllerType.IsSubclassOf(typeof(WebApiController)))
        {
            return (IHttpController) _container.GetInstance(controllerType);
        }

        return _original.Create(request, controllerDescriptor, controllerType);
    }
}

报名人数:

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new ApiControllerActivator(container, GlobalConfiguration.Configuration.Services.GetHttpControllerActivator()));

我需要处理控制器的任何处置,还是由框架处理?

Do I need to handle any disposal of the controller

简短的回答是:只要您使用 RegisterWebApiControllers() 扩展方法注册您的 Web API 控制器,就不需要处理您的控制器。

长答案是,当您调用 RegisterWebApiControllers 时,Simple Injector 实际上 根本不会 处理您的控制器,但您会得到一个 VerificationException当您调用 Container.Verify().

时在您的控制器之一中覆盖 Dispose(bool)

推理如下:Simple Injector 只会处理注册为 ScopedSingleton 的一次性 classes。 Transient 永远不会处理注册。然而,RegisterWebApiControllers 扩展方法将控制器注册为 Transient.

在 Simple Injector 中注册一次性 Transient 时,通常会在调用 Verify 时引起 DisposableTransientComponent 警告。但是,由于 ApiController 基 class 确实实现了 IDisposable,但是它的 Dispose(bool) 方法是一个空操作,不处理它不是问题,除非派生控制器显式覆盖 Dispose(bool).

因此,RegisterWebApiControllers 在进行注册时只是简单地抑制了此警告。但是,当它发现派生控制器 class 确实 覆盖 Dispose(bool) 时,它会放弃抑制,您会看到 Verify() 警告您一次性类型,因为不丢弃这种类型会很麻烦。

这种行为背后的想法是,实际上很少需要在控制器上实现一次性逻辑,因为控制器本身通常不必处理非托管资源。这通常是较低级别的组件会做的事情,但是,当正确注册时,这些组件将由 Simple Injector 处理。如果您有一个具有处理逻辑的控制器,您应该考虑对其进行重构并将该资源从控制器中移出到另一个组件中。

在极少数情况下,在控制器本身上配置逻辑最有意义,您将不得不:

  • 将该特定控制器注册为 Scoped
  • 或者抑制该控制器上的警告并使用 container.RegisterInitializer<MyControllerType>(c => Lifestyle.Scope.RegisterForDisposal(container, c));
  • 在请求的活动 Scope 中注册该控制器以进行处置