c# - OWIN 中间件 + Web API + 简单注入(inject)器

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

我目前使用的 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 永久缓存此实例。

您在这里有两个选择:

  • 确保中间件组件可以用作 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/

    相关文章:

    c# - 一个 Where() 子句中的多个 Any() LINQ

    c# - DetailsView.ItemInserted 事件查找主键(DataKey)

    c# - 在 .NET TextBox 上设置光标的当前行

    javascript - 在调用之间保留安全 token

    c# - 使用 HttpClient 和 Web API 方法 [FromBody] 参数发布到 Web API 最终为空

    c# - 在 Windows 任务计划程序中更改已计划任务的运行时间

    c# - 无法从特定角色中删除用户

    c# - 不可变类和统一应用程序 block

    javascript - AngularJS 种子 : putting JavaScript into separate files (app. js、controllers.js、directives.js、filters.js、services.js)

    dependency-injection - hk2:为什么bind(X.class).to(X.class)