简单注入器/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 AsyncScopedLifestyle。 ThreadScopedLifestyle
是线程专有的,而 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
方法末尾的示例中)。
我正在用 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 AsyncScopedLifestyle。 ThreadScopedLifestyle
是线程专有的,而 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
方法末尾的示例中)。