简单注入器/IoC - Windows 队列处理器的服务和请求周期

Simple Injector / IoC - Windows Service and Request Cycles of a Queue Processor

我正在用 C# 编写一个队列处理器作为 Windows 服务。后端队列机制为MongoDB。队列的目的是 运行 来自我们主网站 (Angular w Web API) 的带外请求。对于每个排队的项目,一个序列化的命令实例 + 序列化的上下文信息,我想

foreach请求周期:
1) 如果当前命令处理程序需要,则新建一个 DbContext (EF)
2) 反序列化 AppContext 并将该信息注入当前命令处理程序

不确定如何在 Simple Injector 中处理这些模式。特别是因为这是定时器的循环,而不是已经为 helpers/classes 编写的 Web 请求。想法?过去我见过其他 IoC 容器使用 lambda 表达式来处理这类事情。只是不确定如何处理我的 #1 和 #2 场景。

每个定时器脉冲都可以被认为是一个新的请求。或者,如果您在一个脉冲中处理多个命令,则每个命令都可以视为一个新请求。

ASP.NET 和 WCF 等一些框架具有请求(Web 请求、WCF 操作等)的概念,这允许 Simple Injector 插入框架的请求模型。因此,Simple Injector 包含 MVC、Web API 和 WCF 的集成包。这些集成包挂钩到框架的请求模型中,这允许您注册每个请求实例而无需执行任何特殊操作。

Windows 然而,服务并未向我们提供这种基于请求的模型。这意味着您将必须手动定义请求边界。这适用于所有 DI 容器;不仅仅是简单的注射器。

Simple Injector 包含两种不同的 Lifestyles,允许您创建显式范围。这些是 ThreadScopedLifestyle and AsyncScopedLifestyleThreadScopedLifestyle 是线程专有的,而 AsyncScopedLifestyle 可以在处理异步操作时使用;它允许作用域流经异步方法调用。

提示:比 ThreadScopedLifestyle 更喜欢使用 AsyncScopedLifestyle,因为它既适用于异步操作,也适用于单线程操作。 ThreadScopedLifestyle 通常只应在 运行 .NET 4.0 应用程序时使用,因为 AsyncScopedLifestyle 仅适用于 .NET 4.5、.NET Core 和 .NET Standard 1.3。

这意味着您必须在容器中启动一个新的 'scope',然后才能从用于处理该命令的容器中解析新服务。例如:

public void ProcessCommand(object command) {
    using (AsyncScopedLifestyle.BeginScope(this.container)) {
        Type handlerType = 
            typeof(ICommandHandler<>).MakeGenericType(command.GetType());

        dynamic handler = container.GetInstance(handlerType);

        handler.Handle((dynamic)command);
    }
}

通过将操作包装在生命周期范围内,我们允许重用服务。我们可以通过使用 AsyncScopedLifestyle:

注册它们来做到这一点
var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

container.Register<IUnitOfWork, DbContextUnitOfWork>(Lifestyle.Scoped);

使用生命周期范围注册的服务将在该范围的持续时间内存在,并在范围被释放时被释放(在 ProcessCommand 方法末尾的示例中)。