C# 简单注入器:寄存器EBAPIController无法抑制可处置瞬态组件警告

C# 简单注入器:寄存器EBAPIController无法抑制可处置瞬态组件警告,c#,asp.net-web-api,simple-injector,C#,Asp.net Web Api,Simple Injector,我可能会简化或误解事情,因此如果这是一个非常愚蠢的问题,我想提前道歉。:) 根据我所看到的文档和代码,我的理解是,当使用简单注入器(在4.3.0上)调用RegisterWebApp控制器时,所有类型ApicController的类都应禁止“一次性瞬态组件”警告 话虽如此,下面的代码抛出了一个无效的配置错误 公共类SimpleInjector配置 { 公共静态无效配置( 容器容器,HttpConfiguration(配置) { container.RegisterWebApp控制器( 配置,Ass

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

根据我所看到的文档和代码,我的理解是,当使用简单注入器(在
4.3.0
上)调用
RegisterWebApp控制器
时,所有类型
ApicController
的类都应禁止“一次性瞬态组件”警告

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

公共类SimpleInjector配置
{
公共静态无效配置(
容器容器,HttpConfiguration(配置)
{
container.RegisterWebApp控制器(
配置,Assembly.GetAssembly(typeof(TestController));
//注册其他必需的类
}
}
配置无效。报告了以下诊断警告: -[一次性瞬态组件]注册为瞬态,但实现IDisposable

没有一个控制器实际上覆盖了
IDisposable
方法,根据我的调试,下面的代码片段(取自最新的
Simple Injector
)应该能够成功调用:

registration.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent,
正当理由:
“Web API注册控制器以便在请求结束时进行处理”+
“调用ApiController.ExecuteAsync。”);
混淆源于这样一个事实:当我用下面的代码修改
Configure
方法时,它确实成功地抑制了警告(即,它可以工作)

publicstaticvoid配置(
容器容器,HttpConfiguration(配置)
{
container.RegisterWebApp控制器(
配置,Assembly.GetAssembly(typeof(TestController));
foreach(容器中的var组件。GetCurrentRegistrations())
{
component.Registration.SuppressDiagnosticWarning(
DiagnosticType.DisposableTransientComponent,
“Web API注册控制器,以便在期间请求结束时进行处理”+
“调用ApiController.ExecuteAsync。”);
}
//注册其他必需的类
}
更让人困惑的是,我们在许多其他项目中使用了Simple Injector,警告抑制似乎在所有项目中都按预期工作,但这就是为什么我认为这是某种配置问题。我试着比较这些项目,找出它们的不同之处,但不幸的是,我还没有想到任何东西

TestController
代码定义为

[RoutePrefix(“api/测试”)]
公共类TestController:ApicController
{
公共IHttpActionResult GetTestString()
{
返回Ok(“来自测试控制器的测试字符串”);
}
}
任何人都曾遇到过这种情况,或者能够解释为什么会发生这种情况?谢谢大家!


更新 感谢Steven提供的以下信息,我设法找出了问题的原因是
SimpleInjector
库之间看起来不一致


SimpleInjector
4.3.0
上,而
SimpleInjector.Integration.WebApi
3.1.0
上。将
SimpleInjector.Integration.WebApi
升级到
4.3.0
成功了。

发生这种情况的最可能原因是,您的Web API控制器实现了
IHttpController
IDisposable
,但没有继承自
ApiController

Web API的
ApiController
基类在其
SendAsync
方法中注册自身以进行处理(通过调用
RegisterForDispose
)。这确保了当请求结束时控制器将被释放

这就是为什么Simple Injector会在继承自ApiController的控制器上抑制诊断警告的原因;WebAPI将确保它们得到处置

由于处置的注册发生在
ApiController
内部,这意味着仅实现
IHttpController
(但不从
ApiController
继承)的控制器将永远不会被处置。这就是为什么Simple Injector仅在
ApiController
衍生产品的情况下抑制此警告的原因

因此,您应该永远不要在Web API控制器上抑制此诊断警告,而不进行其他预处理,以确保您的控制器被处置

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

但是,如果该控制器确实需要处理,您可以覆盖其注册,使其成为
livelity.Scoped
。这确保了该类型由简单的喷油器处理:

container.RegisterWebApp控制器( 配置,Assembly.GetAssembly(typeof(TestController))

container.Options.AllowOverridingRegistrations=true;
容器。寄存器(生活方式。范围);
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));
container.GetRegistration(typeof(MySpecialController)).Registration
.SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent,
“我们手动处理。”);
容器注册表初始化器(c=>
GetCurrentScope(container.RegisterForDisposal(c));
container.GetRegistration(typeof(MySpecialController)).Registration
    .SuppressDiagnosticWarning(DiagnosticType.DisposableTransientComponent, 
        "We dispose manually.");

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