コンテキスト切り替えと IMessageSink

実際に4つの Contribute を登録して実行することで、前回の予測は大幅に間違っていることを確認できた。
MethodLogger proxy.XXX() に最も近い場所にいるのは EnvoySink であり、ClientContextSink が1度も呼び出されていないことに注意しなければならない。


ClientContextSink と ServerContextSink は、その名前に Context と付くだけにコンテキスト切り替えに強く依存したものであることがわかった。
実際に ClientContextSink の呼び出しを行うためには、2つの異なるコンテキストに束縛された ContextBoundObject a, b を用意して、a から b のメソッドを呼び出す必要がある。*1

public interface ITest
{
  void test();
}

public class Base : ContextBoundObject
{
  public void call(ITest it)
  {
    it.test();
  }
}

[ContextA]
public class A : Base, ITest {}

[ContextB]
public class B : Base, ITest {}

このような感じの状態をイメージしてほしい。A, B の各クラスのインスタンスは、それぞれ ContextA, ContextB に対して IsContextOK() が true を返すとする。


この状態で、A.call() に対して B を渡すと、call() 内における test() の呼び出しはContextA から ContextB へのコンテキストスイッチが発生するため、

  1. ContextB.EnvoySink(ContextA)
  2. ContextA.ClientContextSink(ContextA)
  3. ContextB.ServerContextSink(ContextB)
  4. ContextB.ObjectSink(ContextB)

という順序で各 Sink が呼び出される。*2
また、A.call() に対して A を渡すと、コンテキストスイッチが発生しないため、すべての Sink は呼び出されない。


これらの結果から、ServerContextSink と ObjectSink の違いが不明瞭ではあるが、残り2つの Sink との違いはかなり明確になった。
最後に問題となる ServerContextSink と ObjectSink の違いだが、はっきりいってぜんぜんわからない。引数の違いがあるのは確かなのだが、コンテキスト内に複数のオブジェクトが存在していても、1回だけしか呼び出されないし、ServerContextSink と完全にセットで呼び出されるので、どちらかで可能なことは反対でも可能であるように見える。

*1:デフォルトコンテキストの ClientContextSink に対して記録を行うことができないため

*2:括弧内は CurrentContext