S2Daoとかでやられてることなので、特に目新しいことはないのですがUnityでもInterceptor使えば同じようなことができるということでお試し。ネタです。
IDataErrorInfoを実装してみよう
Interceptor使ってIDataErrorInfoを実装してみる遊び。例えば以下のようなクラスを準備。インデクサーは、インターセプターで実装をしてもらうので空っぽ実装。
public class Person : IDataErrorInfo { public string Error { get; private set; } // Interceptorで実装してもらう public virtual string this[string columnName] { get { throw new NotImplementedException(); } } [Required(ErrorMessage = "名前を入力してください")] public string Name { get; set; } }
UnityのインターセプターはIInterceptorBehaviorインターフェースを実装して作る。
public class DataErrorInfoImplementationBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { yield return typeof(IDataErrorInfo); } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { // インデクサーかどうか if (input.MethodBase.Name != "get_Item" || input.Arguments.Count != 1) { return getNext()(input, getNext); } // インデクサーならプロパティの検証 var ctx = new ValidationContext(input.Target, null, null) { MemberName = input.Arguments[0] as string }; var results = new List<ValidationResult>(); var success = Validator.TryValidateProperty( input.Target.GetType().GetProperty(ctx.MemberName).GetValue(input.Target, null), ctx, results); if (success) { // 検証結果がOKなら空文字を返す return input.CreateMethodReturn(""); } // 検証エラーがあるならエラーの内容を返す return input.CreateMethodReturn(results.First().ErrorMessage); } public bool WillExecute { get { return true; } } }
Invokeメソッドが肝です。getNext引数が癖が強いけど、こういうものだと覚えてしまえばなんとかなるかな・・・。
そしてお試し。
var container = new UnityContainer(); // Interceptorを有効化 container.AddNewExtension<Interception>(); // Personクラスは仮想メソッドをインターセプトして、DataErrorInfoImplementationBehaviorでインターセプトするぜ container.RegisterType<Person>( new Interceptor<VirtualMethodInterceptor>(), new InterceptionBehavior<DataErrorInfoImplementationBehavior>()); // コンテナからインスタンスを取得して動くか試してみる var p = container.Resolve<Person>(); Console.WriteLine("ErrorMessage: {0}", p["Name"]); p.Name = "aaa"; Console.WriteLine("ErrorMessage: {0}", p["Name"]);
実行結果はうまく動いた!!
ErrorMessage: 名前を入力してください ErrorMessage:
ということで、インターフェース実装するのがめんどくさかったら、UnityとかのDIコンテナがもってる疑似AOPみたいな機能を使って実装してもらうということも出来るということを頭の片隅に入れておいてもいいかもしれない。