Simple Injector:RegisterWebApiController无法抑制DisposableTransientComponent警告

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

我可能会简化或误解事物,所以如果这是一个非常愚蠢的问题,我想提前道歉。 :)

基于我见过的文档和代码,我的理解是当使用Simple Injector(在RegisterWebApiController上)调用4.3.0时,对于所有类型为ApiController的类,应该禁止“Disposable Transient Component”警告。

话虽如此,下面的代码抛出了无效的配置错误

public class SimpleInjectorConfiguration
{
    public static void Configure(
        Container container, HttpConfiguration configuration)
    {
        container.RegisterWebApiControllers(
            configuration, Assembly.GetAssembly(typeof(TestController)));

        //Register the other required classes
    }
}

配置无效。报告了以下诊断警告: - [Disposable Transient Component]已注册为transient,但实现了IDisposable。

没有任何控制器实际覆盖IDisposable方法,并且从我可以调试的,下面的代码片段(取自最新的Simple Injector source)应该被成功调用:

registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent,
    justification:
        "Web API registers controllers for disposal when the request ends during the " +
        "call to ApiController.ExecuteAsync.");

混淆来自这样的事实:当我用下面的代码修改Configure方法时,它确实成功地抑制了警告(即它有效)。

public static void Configure(
    Container container, HttpConfiguration configuration)
{
    container.RegisterWebApiControllers(
        configuration, Assembly.GetAssembly(typeof(TestController)));

    foreach (var component in container.GetCurrentRegistrations())
    {
        component.Registration.SuppressDiagnosticWarning(
            DiagnosticType.DisposableTransientComponent, 
    "Web API registers controllers for disposal when the request ends during " +
        "the call to ApiController.ExecuteAsync.");
    }

    //Register the other required classes
}

为了增加混乱,我们在许多其他项目中使用了Simple Injector,并且警告抑制似乎在所有这些项目中都有效,但这就是为什么我认为这是某种配置问题。我已经尝试比较这些项目以找到不同的东西,但不幸的是我还没有想出任何东西。

TestController代码定义为

[RoutePrefix("api/Test")]
public class TestController : ApiController
{
    public IHttpActionResult GetTestString()
    {
        return Ok("Test String from Test Controller");
    }
}

任何人都遇到过这个或者可以解释为什么会发生这种情况?谢谢!


更新

感谢下面Steven提供的信息,我设法弄清楚问题是因为SimpleInjector库之间看起来不一致。

SimpleInjector4.3.0,而SimpleInjector.Integration.WebApi3.1.0。将SimpleInjector.Integration.WebApi升级到4.3.0就可以了。

c# asp.net-web-api simple-injector
1个回答
1
投票

发生这种情况的最可能原因是因为您的Web API控制器同时实现了IHttpControllerIDisposable,但不会继承ApiController

Web API的ApiController基类在其RegisterForDispose方法中注册自己(通过调用SendAsync)。这可确保在请求结束时控制器将被处理。

这就是Simple Injector在继承ApiController的控制器上禁止诊断警告的原因。 Web API将确保它们将被处置。

由于处理的注册发生在ApiController内部,它确实意味着一个简单地实现IHttpController(但没有继承ApiController)的控制器将永远不会被处置。这就是为什么Simple Injector仅在ApiController衍生物的情况下抑制此警告的原因。

因此,您不应该在Web API控制器上禁止出现此诊断警告,而不会采取保护控制器的其他预先配置。

如果您的控制器没有有意义的配置逻辑,则应从控制器中删除IDisposable接口。这消除了问题。控制器应该很少需要处理逻辑,因为您通常应该将其提取给其他服务;控制器通常不应该依赖于它自己创建的资源。

但是,如果该控制器确实需要处理,您可以覆盖其注册以成为Lifestyle.Scoped。这确保了Simple Injector处理类型:

container.RegisterWebApiControllers(configuration,Assembly.GetAssembly(typeof(TestController)));

container.Options.AllowOverridingRegistrations = true;
container.Register<MySpecialController>(Lifestyle.Scoped);
container.Options.AllowOverridingRegistrations = false;

或者,您可以仅在该特定控制器上禁止诊断警告,并烹饪一个确保其处置的特殊代理:

container.GetRegistration(typeof(MySpecialController)).Registration
    .SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent, 
        "We dispose manually.");

container.RegisterInitializer<MySpecialController>(c =>
    Lifestyle.Scoped.GetCurrentScope(container).RegisterForDisposal(c));
© www.soinside.com 2019 - 2024. All rights reserved.