我需要这个来简化以下典型的例行操作的实现:
我想在发送消息之前捕获用户的上下文,并在处理消息之前恢复用户上下文,类似于以下遗留示例中的操作方式:https://github.com/rebus-org/RebusSamples/tree/master/old/UserContextHeaders
我想在处理邮件之前对邮件进行验证和重复数据删除,并在处理邮件后记录结果。
答案 0 :(得分:1)
正如问题作者正确找到的那样,Rebus.Events包提供了可读和可访问的方式,可以在发送/接收消息之前/之后挂钩。
如果这就足够了,我肯定会这样做。
但是,如果是你想WRAP try/finally
内的单个消息的整个处理(我建议你在恢复发送用户的身份来处理消息时),你可能想看看基于本机的扩展机制关于装饰者。
您可以阅读the wiki page about extensibility,了解如何通过修改其管道来扩展Rebus。
例如,要在处理消息之前和之后对当前的声明主体执行某些操作,您可以实现这样的“传入管道步骤”:
[StepDocumentation("Write a nice descriptoion here")]
class MyIncomingStep : IIncomingStep
{
public async Task Process(IncomingStepContext context, Func<Task> next)
{
var originalPrincipal = ClaimsPrincipal.Current;
try
{
// establish user identity here
ClaimsPrincipal.Current = ...
// handle message
await next();
}
finally
{
ClaimsPrincipal.Current = originalPrincipal;
}
}
}
然后您可以使用“步进注入器”装饰Rebus'IPipeline
,声明性地说明您希望插入步骤的管道中的位置:
.Options(o => {
o.Decorate<IPipeline>(c =>
{
var pipeline = c.Get<IPipeline>();
var stepToInject = new TransactionScopeIncomingStep(transactionOptions);
return new PipelineStepInjector(pipeline)
.OnReceive(stepToInject, PipelineRelativePosition.Before, typeof(DispatchIncomingMessageStep));
});
})
然后 - 为了让事情变得漂亮 - 你可以将上面的代码包含在OptionsConfigurer
的扩展方法中,从而提供更漂亮的配置语法:
.Options(o => {
o.RestoreClaimsPrincipalWhenHandlingMessages();
})
或者您认为应该被称为的任何内容:)
发送消息时,一切都以类似的方式工作,你只想
//....
return new PipelineStepInjector(pipeline)
.OnSend(stepToInject, PipelineRelativePosition.Before, typeof(SerializeOutgoingMessageStep));
代替。