IHttpControllerActivator中的控制器处理

时间:2018-07-30 08:53:22

标签: c# simple-injector

我为自己的Web api控制器使用了自定义IHttpControllerActivator,并与简单的注入器一起使用:

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()));

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

1 个答案:

答案 0 :(得分:1)

  

我需要处理控制器的任何处置

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

长答案是,当您调用RegisterWebApiControllers时,Simple Injector实际上将完全处置您的控制器,但是当您覆盖{{ 1}},当您致电VerificationException时在其中一个控制器中。

原因如下:Simple Injector仅在将一次性类注册为Dispose(bool)Container.Verify()时处置一次性类。 Scoped注册永远不会被丢弃。但是,Singleton扩展方法将控制器注册为Transient

在Simple Injector中注册一次性RegisterWebApiControllers时,通常会在调用Transient时引发Transient警告。但是,由于DisposableTransientComponent基类确实实现了Verify,但是它的ApiController方法是no-op,不处理它不是问题,除非派生的控制器显式重写{ {1}}。

因此,IDisposable仅在进行注册时禁止显示此警告。但是,当发现派生的控制器类确实覆盖Dispose(bool)时,它将丢弃该抑制,并且您会看到Dispose(bool)会警告您有关此可抛弃类型的信息,因为未处置此类类型会是个问题。

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

在极为罕见的情况下,在控制器本身上配置逻辑是最有意义的,您要么必须:

  • 将该特定控制器注册为RegisterWebApiControllers
  • 或者禁止显示该控制器上的警告,并使用Dispose(bool)在请求的活动Verify()中注册该控制器以进行处理