我目前使用的 WebApiRequestLifestyle 具有默认范围的生活方式。我想在 OWIN 中间件和 API Controller 之一中注入(inject)服务,并且服务的范围应该仍然是 WebAPI,即对于整个请求,应该只有一个服务实例。
public class TestMiddleware : OwinMiddleware
{
private readonly ITestService _testService;
public TestMiddleware(OwinMiddleware next, ITestService testService) : base(next)
{
_testService = testService;
}
public override async Task Invoke(IOwinContext context)
{
var test = _testService.DoSomething();
await Next.Invoke(context);
}
}
public class ValuesController : ApiController
{
private readonly ITestService _testService;
public ValuesController(ITestService testService)
{
_testService = testService;
}
}
整个请求的 ITestService 实例应该相同。我应该如何注册中间件?
这就是我现在的做法:
using (container.BeginExecutionContextScope())
{
var testService = container.GetInstance<ITestService>();
app.Use<TestMiddleware>(testService);
}
这种方法的问题是 - ITestService 的一个实例在注册期间为中间件创建并永久保留(如单例),并且对于每个 webapi 请求,都会创建一个新实例并在 Controller 之间共享(webapi 范围)
请不要向我指出这些问题 - WebApi + Simple Injector + OWIN
Injecting a dependency into OWIN Middleware and per web-request with Simple Injector
最佳答案
OWIN的Use<T>
方法注册提供的T
作为 OWIN 管道中的单例,无论您在容器中配置该类型的生命周期是什么。因此,当您在事件范围内解析中间件时,您(隐含地)告诉 OWIN 永久缓存此实例。
您在这里有两个选择:
确保中间件组件可以用作单例很容易。只需在 Simple Injector 中将其注册为单例,当您调用
Verify()
, Simple Injector 会检测这个组件是否可以作为单例使用,或者是否有生命周期较短的依赖。然而,这确实意味着所有依赖项都应该是单例,并且运行时数据(如 DbContext 和其他数据对象)应该在构建对象图之后通过方法调用传递。我认为这是一个很好的做法,但这可能是您的应用程序的一个很大的变化,并且可能是一个很大的转变。因此,我认为这超出了这个问题的范围,所以你应该选择选项 2。如果您的中间件组件具有较短生命周期的依赖关系,您应该根据请求请求解析该中间件。这意味着您不应该使用 OWIN 的
Use<T>(middleware)
方法,因为这会使它成为单例。这是如何做到的:
app.Use(async (context, next) =>
{
var middleware = container.GetInstance<TestMiddleware>();
await middleware.Invoke(context, next);
});
请注意
TestMiddleware
在每个请求上解决。这使 Simple Injector 可以完全控制已构建的对象图。然而,这意味着您需要对您的 TestMiddleware
进行小幅调整。类(class)。它应该是这样的:public sealed class TestMiddleware
{
private readonly ITestService _testService;
public TestMiddleware(ITestService testService)
{
_testService = testService;
}
public async Task Invoke(IOwinContext context, Func<Task> next)
{
var test = _testService.DoSomething();
await next();
}
}
请注意
OwinMiddleware
参数从构造函数中移除,并替换为 Func<Task>
Invoke
中的参数方法。这允许 Simple Injector 构造类型,因为它的构造函数将不再包含任何运行时参数。记住:通过构造函数编译时依赖,通过方法调用编译运行时数据。另请注意,中间件不是从
OwinMiddleware
继承的。了。由于中间件没有注入(inject)封装的中间件,因此从它继承变得毫无用处。
关于c# - OWIN 中间件 + Web API + 简单注入(inject)器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39415969/