3

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 });

ハンドラーの寿命を制御するために、私はウィンザー城のスコープ付きライフスタイルを使用します

_container.Register(
  Component.For<IHandleMessages<CustomerCreated>, IHandleMessages<PreferredCustomer>>)
    .ImplementedBy<CustomerHandler>().LifestyleScoped());

そして、ScopedUnitOfWorkをインスタンス化するカスタムUnitOfWorkManager

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!!!");
    }
}

CustomUnitOfWorkManagerを使用するように最終的に構成されたRebus

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内のデータストアに対するトランザクション管理も含めることができます。

4

1 に答える 1

0

あなたはそれを釘付けにしているように聞こえます:)

正しいコミット/ロールバック動作が得られれば、それは問題なくダンディだと思います。

別の方法に興味がある場合は、PerTransportMessageCastleWindsorスコープアクセサーを確認することをお勧めします。次のように使用できます。

container.Register(
    Component
        .For<ISomething>()
        .ImplementedBy<Whatever>()
        .LifestyleScoped<PerTransportMessage>()
);

これは、まったく同じ動作を実現できるはずです。

于 2013-03-25T15:20:02.347 に答える