我希望批量处理相关邮件,例如使用Rebus服务总线在同一范围/事务中使用相同的处理程序(相同实例)处理事件CustomerCreated和PreferredCustomer。
同一个处理程序正在处理这两个消息/事件:
class CustomerHandler : IHandleMessages<CustomerCreated>, IHandleMessages<PreferredCustomer>
{
Customer Customer { get; set; }
public CustomerHandler() {
Customer = new Customer();
}
public void Handle(CustomerCreated message) {
Customer.Name = message.Name;
Console.WriteLine(Customer);
}
public void Handle(PreferredCustomer message) {
Customer.Rebate = message.Rebate;
Console.WriteLine(Customer);
}
}
发送消息时,我使用批处理操作(在NServiceBus中传输消息)
bus.Advanced.Batch.Publish(
new CustomerCreated() { Name = "Anders" },
new PreferredCustomer() { Rebate = 10 });
为了控制处理程序的生命周期,我使用Windsor Castle’s Scoped lifestyle
_container.Register(
Component.For<IHandleMessages<CustomerCreated>, IHandleMessages<PreferredCustomer>>)
.ImplementedBy<CustomerHandler>().LifestyleScoped());
一个自定义UnitOfWorkManager,用于实现ScopedUnitOfWork
class CustomUnitOfWorkManager : IUnitOfWorkManager
{
private readonly IWindsorContainer _container;
public CustomUnitOfWorkManager(IWindsorContainer container) {
_container = container;
}
public IUnitOfWork Create() {
return new ScopedUnitOfWork(_container);
}
}
class ScopedUnitOfWork : IUnitOfWork
{
private readonly IDisposable _scope;
public ScopedUnitOfWork(IWindsorContainer container) {
// Begin transaction
_scope = container.BeginScope();
}
public void Dispose() {
_scope.Dispose();
}
public void Commit() {
// Commit transaction
Console.WriteLine("Commiting");
}
public void Abort() {
// Rollback transaction
Console.WriteLine("Aborting!!!");
}
}
最后配置Rebus以使用CustomUnitOfWorkManager
var bus = Configure.With(new WindsorContainerAdapter(_container))
.Transport(t => t.UseMsmqAndGetInputQueueNameFromAppConfig())
.MessageOwnership(d => d.FromRebusConfigurationSection())
.Events(x => x.AddUnitOfWorkManager(new CustomUnitOfWorkManager(_container)))
.CreateBus()
.Start();
这是正确的方法吗?
我的有限测试显示这应该有效。我甚至可以扩展它以包括对ScopedUnitOfWork中的数据存储的事务管理。
答案 0 :(得分:0)
听起来你已经钉了它:)
如果你得到了正确的提交/回滚行为,那么我会说它很好而且花花公子。
如果您对替代方案感兴趣,可能需要查看PerTransportMessage
Castle Windsor范围访问器 - 它可以像这样使用:
container.Register(
Component
.For<ISomething>()
.ImplementedBy<Whatever>()
.LifestyleScoped<PerTransportMessage>()
);
应该能够达到完全相同的行为。