DynamicMessageSink
最後に残ったこいつを試さずに終わることはできない。
こいつを試すのは他の4つの Sink と違ってちょっと面倒だ。
まず、何が違うかというと IContextProperty の実装クラスで IDynamicProperty を実装し、IContributeDynamicMessageSink を実装する。
最初から1つのインターフェスでいいやん、とか突っ込んでみたくもなる。
その上で、利用するコンテキストかオブジェクトを指定して Context.RegisterDynamicProperty を呼び出してやらないと登録されないのだが、コンテキスト毎、オブジェクト毎に登録ができると考えれば、実は便利かもしれない?
さて、こいつは IMessageSink とは異なり、メッセージ交換の開始と終了で別々のメソッドを呼び出される。それだけ考えるとログ記録には結構もってこいのヤツともいえる。
問題はいつ呼び出されるか、なのだが……。
- ContextB.EnvoySink
- ContextA.ClientContextSink
- ContextA.ProcessMessageStart(コンテキストに対する登録時)
- context switch(CurrentContextが入れ替わる)
- ContextB.ProcessMessageStart(コンテキストに対する登録時)
- ContextB.ServerContextSink
- ContextB.ObjectContextSink
- ContextB.ProcessMessageStart(オブジェクトに対する登録時)
- context switch(CurrentContextが入れ替わる)
- ContextB.ProcessMessageFinish(コンテキストに対する登録時)
といったかんじの記録が手に入る。
呼び出し元を意識した記述に直すと、
ContextB.EnvoySink.ProcessMessage() { ContextA.ClientContextSink() } ContextA.ClientContextSink() { if RegisterForContext ContextA.ProcessMessageStart(); ContextSwitch(); if RegisterForContext ContextA.ProcessMessageFinish(); } ContextSwitch() { ContextB.ServerContextSink(); } ContextB.ServerContextSink() { if RegisterForContext ContextB.ProcessMessageStart(); ContextB.ObjectContextSink(); } ContextB.ObjectContextSink() { if RegisterForObject ContextB.ProcessMessageStart(); }
といった感じになっているので、扱い方次第では便利なタイミングと言えるかもしれない。
ProcessMessageFinish() が ProcessMessageStart() と1対1になっていないところも注意が必要だろう。