4

したがって、Ninjectを介してメッセージハンドラーをインスタンス化するメッセージバスがあります。ロギング、トランザクション管理などの横断的関心事でハンドラーを装飾したいと思います。

バインディングを次のように設定します。

kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>()
    .WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>));

これは、特定のメッセージタイプのハンドラーが1つある場合はいつでも素晴らしく機能します。ただし、複数のハンドラーを定義している場合:

kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>()
    .WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind<IMessageHandler<int>>().To<IntHandlerTwo>()
    .WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>));

Ninjectは、デコレータを見つけてメッセージバスに注入し、その後、両方のハンドラをデコレータコンストラクタに注入しようとしますが失敗します。

public HandlerDecorator(IMessageHandler<T> handler)

ハンドラーのリストを受け入れるようにデコレーターを変更してみませんか?私はこれについて考えました、しかしそれはハンドラーの目的を打ち負かします。複数のデコレータを簡単に透過的にチェーンできるようにしたいと思います。の各インスタンスはIMessageHandler<T>、まったく新しいハンドラーのチェーンを取得する必要があります。

ここで話していることを説明するサンプルテストライブラリをGitHubに公開しました。

Ninjectでこれを行う方法はありますか?

4

2 に答える 2

3

使用する

kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>().WhenParentNamed("One");
kernel.Bind<IMessageHandler<int>>().To<IntHandlerTwo>().WhenParentNamed("Two");
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>)).Named("One");
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>)).Named("Two");

また、ほとんどのバスフレームワークには、メッセージハンドラーの装飾を行う方法があることに注意してください。最初にそこを見てください。

于 2012-11-16T11:46:18.190 に答える
0

これらのハンドラーをコンポジットでラップする必要があります。

public class CompositeMessageHandler<T> : IMessageHandler<T>
{
    private readonly IEnumerable<IMessageHandler<T>> handlers;

    CompositeMessageHandler(IEnumerable<IMessageHandler<T>> handlers)
    {
        this.handlers = handlers;
    }

    public void Handle(T message)
    {
        foreach (var handler in this.handlers)
        {
            handler.Handle(message);
        }
    }
}

このコンポジットは、デコレータに再び注入できます。または、逆の方法で行う必要があります。各ハンドラーをデコレーターでラップし、それらをコンポジットにラップします。

これをNinjectに登録する方法はわかりませんが。

于 2012-11-08T10:33:19.073 に答える