NullObjectパターン
http://d.hatena.ne.jp/akiramei/20071010/1192038349
↑はるか昔に似たようなことやった気がしていたのですが、はてなで日記を書く前でした。折角なので、数年間更新していない自分のHPからコードを持ってきてGeneric対応させてみました。当時(2003年)は、RealProxyがマイブームだった模様(笑)。
using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Proxies; class NullProxy<T> : RealProxy { private static readonly Dictionary<Type, WeakReference> hash = new Dictionary<Type, WeakReference> (); static readonly object syncObj = new object (); private NullProxy () : base (typeof(T)) { } /// <summary> /// メソッド呼び出しに割り込んで何もしないで抜ける。 /// メソッドに戻り値がある場合、参照型ならnull、値型なら初期値を返す。 /// </summary> /// <param name="msg">メッセージ通信オブジェクト</param> /// <returns>ReturnMessageオブジェクト</returns> public override IMessage Invoke (IMessage msg) { IMethodCallMessage req = msg as IMethodCallMessage; object o = null; Type t = *1 o = Activator.CreateInstance (t); ReturnMessage rm = new ReturnMessage (o, null, 0, req.LogicalCallContext, req); return rm; } // 型毎にインスタンスは一つしか作らない public static T GetInstance () { lock (syncObj) { NullProxy<T> result = null; Type t = typeof (T); WeakReference w = hash.ContainsKey(t) ? hash [t] : null; if (w != null) result = w.Target as NullProxy<T>; if (result == null) { result = new NullProxy<T> (); hash[t] = new WeakReference (result); } // 透過プロキシを返す return (T)result.GetTransparentProxy (); } } } /// <summary> /// MarshalByRefObjectから継承する必要がある /// </summary> class Person : MarshalByRefObject { private readonly string name = "Taro"; private readonly int age = 20; public int Foo() { return 42; } public void Bar() { Console.WriteLine ("Bar"); } public override string ToString () { return String.Format ("Name={0}, Age={1}", name, age); } } class Program { static void Main() { Person cp = NullProxy<Person>.GetInstance (); // 42が表示・・・されない Console.WriteLine (cp.Foo ()); // Barが表示・・・されない cp.Bar (); // Name=Taro, Age=20が表示・・・されない Console.WriteLine (cp.ToString ()); } }
*1:MethodInfo)req.MethodBase).ReturnType; if (t.IsValueType) if (t != typeof (void