c# - 简易喷油器 : RegisterWebApiController failing to suppress DisposableTransientComponent warning

标签 c# asp.net-web-api simple-injector

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

根据我看过的文档和代码,我的理解是,当使用简单注入(inject)器(在 4.3.0 上)调用 RegisterWebApiController 时,“一次性 transient 组件"对于类型为 ApiController 的所有类,应该禁止显示警告。

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

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

        //Register the other required classes
    }
}

The configuration is invalid. The following diagnostic warnings were reported: -[Disposable Transient Component] is registered as transient, but implements IDisposable.

实际上没有一个 Controller 覆盖 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 就成功了。

最佳答案

发生这种情况的最可能原因是因为您的 Web API Controller 同时实现了 IHttpControllerIDisposable,但没有继承自 ApiController

Web API 的 ApiController 基类在 SendAsync 方法中注册自身以进行处理(通过调用 RegisterForDispose)。这确保了 Controller 将在请求结束时得到处置。

这就是为什么 Simple Injector 会抑制继承自 ApiController 的 Controller 上的诊断警告; Web API 将确保它们得到处置。

由于处置注册发生在 ApiController内部,这确实意味着 Controller 只实现了 IHttpController(但没有继承自 ApiController) 永远不会被释放。这就是为什么 Simple Injector 仅在 ApiController 派生的情况下抑制此警告。

因此,您应该永远不要在您的 Web API Controller 上抑制此诊断警告,而不采取其他保证您的 Controller 已被处置的预防措施。

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

但是,如果该 Controller 确实需要处置,您可以覆盖其注册以成为 Lifestyle.Scoped。这确保类型由简单注入(inject)器处理:

容器.RegisterWebApiControllers( 配置, Assembly.GetAssembly(typeof(TestController)));

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

或者,您可以仅在该特定 Controller 上抑制诊断警告,并烹制一个特殊委托(delegate)以确保其处置:

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

container.RegisterInitializer<MySpecialController>(c =>
    Lifestyle.Scoped.GetCurrentScope(container).RegisterForDisposal(c));

关于c# - 简易喷油器 : RegisterWebApiController failing to suppress DisposableTransientComponent warning,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52082514/

相关文章:

c# - 从 XAML 将 Window 对象绑定(bind)到 viewmodel 属性

C# - 字符串比较是错误的,尽管我检查过

c# - 确定是否通过window.open()命令打开了aspx页面

c# - 如何将业务层映射到 UML 中的模型对象?

javascript - 将 ng-click 值传递给一个 Controller 并在另一个 Controller 中使用它

c# - 简单注入(inject)器 - 将 url 值注入(inject)到服务构造函数中

c# - 按名称访问唯一数组

c# - 使用数据参数调用Web api get方法c#

asp.net-mvc - 简单的注入(inject)器手动注册 Controller

c# - 获取 Simple Injector 的容器实例