Invoke() を実装する

Invoke() は、メソッド呼び出しである。
何をしなければならないかはわかりきっている。この場合は Add() を実行するだけだ。
メソッドに戻り値があるように、TransparentProxy に対する操作は、必ずなんらかのメッセージを応答として返さなければならない。
メソッド呼び出しが IMethodCallMessage に対して、その応答はIMethodReturnMessage であり、戻り値のほかに ref や out のパラメータのための新しい値や、例外の発生などもサポートする。
このインターフェスを自力で実装する必要はなく、RealProxy 同様に ReturnMessage クラスを利用すれば簡単に済ますことができる。

  private int form1_current = 0;

  public override IMessage Invoke(IMessage msg)
  {
    // メソッド呼び出しは IMethodCallMessage である
    IMethodCallMessage request = msg as IMethodCallMessage;

    // メソッドの呼び出しを記録する
    Debug.WriteLine(request.MethodName + "が呼び出されました!");

    // 結果を返すための変数
    IReturnMessage ret = null;

    switch (request.MethodName)
    {
      case "Add":
        // 戻り値として現在値を保持した ReturnMessage を生成する
        ret = new ReturnMessage(this.form1_current, null, 0, request.LogicalCallContext, request);

        // 最初の引数の値を現在値に足す
        form1_current += (int) request.Args[0];
        break;

      default:
        // その他すべての呼び出しは未実装である例外を発行する
        ret = new ReturnMessage(new NotImplementException(), request);
        break;
    }

    return ret; 
  }

Add メソッドを実装し適切な値を返す。
同時にそのほかのメソッド呼び出しに対しては例外を発行する実装を提供する。
すべてのメソッド呼び出しは Invoke() に到達するので、TransparentProxy に対して ToString() などのメソッドを呼び出された場合などに、この処理を通ることになる。

続きは、また明日

キーワード展開の限界に達すると、はてなダイアリーで書く魅力が薄れるから(笑)*1

また、現在までのコード片はまったく動作しない。
間違ったことを書いている可能性はあるが、動かないコードを書かせるための内容になっているわけではない、しかし動かない。

明日以降は、

  • なぜ new Form1() が必要だったか
  • より汎用的な Invoke() の実装
  • this.Add() と form1.Add() の違い
  • MarshalByRefObject クラス
  • DAMN internal
  • FieldGetter と FieldSetter
  • this.Add() 再び
  • ContextBoundObject クラス

というような話が展開されていく・・・予定。
# 三連休、全部仕事なんだけどね。

*1:いや、こんな程度ではぜんぜん達しないようですけどね