イベントリスナーの登録

あるオブジェクト「A」で発生したイベントをあるオブジェクト「B」に伝える場合、通常「event」と「delegate」か
「Observer」パターンを利用するかのどちらかだと思う。
そうした場合、どちらかが片方に依存する事になるが、これが嫌な場合(そんなんあるかなぁ?)もしくは、そもそも依存できない場合Spring.NETの「IApplicationEventListener」でこの問題を解決する事ができる。

まずはイベントを通知するクラスを作る。

public class Hoge : IApplicationContextAware {
    private IApplicationContext context;
    public IApplicationContext ApplicationContext {
        get { return context; }
        set { context = value; }
    }
    pubilc void Do(string message) {
        // なんかする。
    }
}

アプリケーションコンテキストを取得するために、「IApplicationContextAware」インターフェースを実装している。(別にこのインターフェースを実装する事が必須ではない)

次にイベントの内容を格納するためのイベント引数クラスを作る。このクラスは「Spring.Context.ApplicationEventArgs」から派生する必要がある。

pubilc class HogeEventArgs : ApplicationEventArgs {
    private string message;
    public string Message {
        get { return message; }
    }
    public HogeEventArgs(string message) {
        this.message = message;
    }
}

次にイベントが通知されるクラスを作る。
このクラスは「Spring.Context.IApplicationEventListener」インターフェースを実装する必要がある。

public class HogeEventListener : IApplicationEventListener {
    public void HandleApplicationEvent(object sender, ApplicationEventArgs e) {
        if(e is HogeEventArgs) {
            // なにかしらの方法で誰かに通知する。
        }
    }
}

そして「Hoge」クラスの「Do」メソッドに以下の処理を追加する。

public void Do(string message) {
    // なんかする。
    ApplicationContext.PublishEvent(this, new HogeEventArgs(message));
}

「IApplicationContext」の「PublishEvent」メソッドで「IApplicationEventListener」を実装したクラスにイベントを通知できる。

もちろんその前にオブジェクトをコンテナに追加しておく必要がある。

<object name="hoge" type="HogeLib.Hoge, HogeLib">
</object>

<!-- 宣言するだけ -->
<object name="hogeEventListener" type="HogeLib.HogeEventListener, HogeLib">
</object>

で、実際動かすところ

public static void Main() {
    IApplicationContext context = new XmlApplicationContext("objects.config");

    Hoge hoge = context.GetObject("hoge");
    // 誰かに通知される。
    hoge.Do("Hello");
}

これで一応、イベントを通知するオブジェクトと通知されるオブジェクトが直接、関係する事はなくなる。
まぁ、DIコンテナを利用した「Observer」パターンやね。

でも、イベントを通知されるクラスがみんなこのインターフェースを実装しなければならないとなると、あまりSpring.NETに依存するのは好ましくないので、やりたくない。
じゃぁ、イベントリスナークラスが仲介者となって、適切なイベント引数にキャストした後、別のオブジェクトにイベントを伝播するとなると、今度はイベントリスナークラスと他のクラスが依存する事になるので、結局は同じ事のような気もする。

まぁ、いろんなオブジェクトに横断的にイベントを伝播したい時に使うための機能なのかなと、勝手に結論付けてみる。