- PR -

RealProxyを使ったNullObjectパターン

1
投稿者投稿内容
mei
大ベテラン
会議室デビュー日: 2003/04/08
投稿数: 114
投稿日時: 2003-08-02 10:14
こんにちは、meiです。

RealProxyクラスの勉強をしていて、
NullObjectパターンに使えそうだったのでサンプルを作ってみたのですが、
戻り値があるメソッドの場合、戻り値の型が違うというエラーになります。
もちろん、戻り値の設定をしていないので当然なんですが・・・

そこで、メソッドの戻り値の型をリフレクションで調べて、
ReturnMessageのReturnValueに設定すれば良いかと思いましたが、
読み取り専用プロパティのため、上手くいきませんでした。

他にも、リフレクションでReturnValueのPropertyInfoを取得して、
SetValueとかやってみましたが、やはり駄目です。
#↑例え上手くいったとしても強引過ぎですが。

ReturnMessageクラスにどうやって戻り値を設定すれば良いのでしょうか?

↓RealProxyクラスを使ったNullObjectパターンのサンプル
コード:
using System;
using System.Collections;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;

// NullObjectを作るプロキシクラス
class NullProxy : RealProxy {
	MarshalByRefObject _target;
	public NullProxy(Type t) : base(t) {
		_target = Activator.CreateInstance(t) as MarshalByRefObject;
	}

	public override IMessage Invoke(IMessage msg) {
		IMethodCallMessage req = msg as IMethodCallMessage;

		// RemotingServices.ExecuteMessageは呼ばず、メソッドは実行しない。
		ReturnMessage rm = new ReturnMessage
			(_target, null, 0, req.LogicalCallContext, req);
		// rm.ReturnValueは読み取り専用なので戻り値が設定出来ない
		return rm;
	}
}

// テストクラス
class MyClass : MarshalByRefObject {
	public void Sub(int x, ref int y, out int z) {
		Console.WriteLine("x={0}, y={1}", x, y);
		z = 10;
	}
	public int Function() {
		return 0;
	}
}


class MyApp
{
	static void Main(string[] args)
	{
		Random r = new Random();
		for (int i = 0; i < 100; ++i) {
			int y = 10;
			int z;
			// 初期値をNullObjectとする
			MyClass my = new NullProxy(typeof(MyClass)).GetTransparentProxy() as MyClass;
			if (r.Next() % 2 == 0) {
				my = new MyClass();
			}
			// myの値はランダムにMyClassまたはNullObject
			my.Sub(i, ref y, out z);
			
			// 戻り値があるメソッドはエラーになる
			// my.Function();
		}
	}
}



mei
大ベテラン
会議室デビュー日: 2003/04/08
投稿数: 114
投稿日時: 2003-08-03 23:13
自己解決しました。

コード:
public override IMessage Invoke(IMessage msg) {
	IMethodCallMessage req = msg as IMethodCallMessage;
	object o = null;

	Type t = ((MethodInfo)req.MethodBase).ReturnType;
	if (t != typeof(void))
		o = Activator.CreateInstance(t);

	ReturnMessage rm = new ReturnMessage
		(o, null, 0, req.LogicalCallContext, req);
	return rm;
}


戻り値は単純に第一引数に渡せば良かったみたい。

ヘルプから引用
>呼び出されたメソッドから、現在の ReturnMessage インスタンスの生成元として返されるオブジェクト。
言われてみればそうなんですが、ちょっと読みとれなかった・・・
1

スキルアップ/キャリアアップ(JOB@IT)