2010-11-29 14 views
2

http://msdn.microsoft.com/en-us/library/ff660851(v=PandP.20).aspxは、IInterceptionBehaviorを実装してINotifyPropertyChangedサポートを追加する方法のサンプルを提供します。サンプルに含まれていないものは、実行時にNotifyPropertyChangedBehaviorを使用するように設定する方法です。私がしたすべてのグーグルが、私に実用的な答えを与えていない。実行時にUnity 2.0を設定してINotifyPropertyChangedを傍受するには?

私はAOPとIoCの初心者ですので、コンセプトが間違っているかもしれません。これは私が何をしたいです:

using Microsoft.Practices.Unity; 
using Microsoft.Practices.Unity.InterceptionExtension; 
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Reflection; 

static class AppMain 
{ 
    public static void Main() 
    { 
     // Configure Unity. 
     var container = new UnityContainer(); 

     container.AddNewExtension<Interception>(); 

     // todo: Register an interface instead of a type. 
     container.RegisterType<Customer>(new Interceptor<VirtualMethodInterceptor>(), 
             new InterceptionBehavior<NotifyPropertyChangedBehavior>()); 

     var propertyChangedCount = 0; 
     var customer = new Customer(); 

     customer.PropertyChanged += (s, e) => propertyChangedCount += 1; 

     // Update customer and send property changed event. 
     customer.FirstName = "what ever"; 

     if (propertyChangedCount != 1) 
     { 
      Console.Write("Failed!"); 
     } 
     else 
     { 
      Console.WriteLine("Success!"); 
     } 

     Console.WriteLine(); 
     Console.WriteLine("Press any key to continue..."); 
     Console.ReadKey(); 

    } 

    static void customer_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     throw new NotImplementedException(); 
    } 

    public class Customer : MarshalByRefObject, INotifyPropertyChanged 
    { 

     private string _firstName; 
     public event PropertyChangedEventHandler PropertyChanged; 

     // todo: Does the property have to be virtual (overridable). 
     public virtual string FirstName 
     { 
      get { return _firstName; } 
      set 
      { 
       _firstName = value; 
       // Unity Interception to do the following RaiseEvent 
       //if (PropertyChanged != null) 
       //{ 
       // PropertyChanged(this, new PropertyChangedEventArgs("FirstName")); 
       //} 
      } 
     } 

    } 

    // Copied from http://msdn.microsoft.com/en-us/library/ff660851(v=PandP.20).aspx 
    class NotifyPropertyChangedBehavior : IInterceptionBehavior 
    { 
     private event PropertyChangedEventHandler propertyChanged; 

     private static readonly MethodInfo addEventMethodInfo = 
      typeof(INotifyPropertyChanged).GetEvent("PropertyChanged").GetAddMethod(); 

     private static readonly MethodInfo removeEventMethodInfo = 
      typeof(INotifyPropertyChanged).GetEvent("PropertyChanged").GetRemoveMethod(); 

     public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 
     { 
      if (input.MethodBase == addEventMethodInfo) 
      { 
       return AddEventSubscription(input, getNext); 
      } 
      if (input.MethodBase == removeEventMethodInfo) 
      { 
       return RemoveEventSubscription(input, getNext); 
      } 
      if (IsPropertySetter(input)) 
      { 
       return InterceptPropertySet(input, getNext); 
      } 
      return getNext()(input, getNext); 
     } 

     public bool WillExecute 
     { 
      get { return true; } 
     } 

     public IEnumerable<Type> GetRequiredInterfaces() 
     { 
      return new[] { typeof(INotifyPropertyChanged) }; 
     } 

     private IMethodReturn AddEventSubscription(IMethodInvocation input, 
                GetNextInterceptionBehaviorDelegate getNext) 
     { 
      var subscriber = (PropertyChangedEventHandler)input.Arguments[0]; 

      propertyChanged += subscriber; 
      return input.CreateMethodReturn(null); 
     } 

     private IMethodReturn RemoveEventSubscription(IMethodInvocation input, 
                 GetNextInterceptionBehaviorDelegate getNext) 
     { 
      var subscriber = (PropertyChangedEventHandler)input.Arguments[0]; 

      propertyChanged -= subscriber; 
      return input.CreateMethodReturn(null); 
     } 

     private static bool IsPropertySetter(IMethodInvocation input) 
     { 
      return input.MethodBase.IsSpecialName && input.MethodBase.Name.StartsWith("set_"); 
     } 

     private IMethodReturn InterceptPropertySet(IMethodInvocation input, 
                GetNextInterceptionBehaviorDelegate getNext) 
     { 
      var propertyName = input.MethodBase.Name.Substring(4); 
      var returnValue = getNext()(input, getNext); 
      var subscribers = propertyChanged; 

      if (subscribers != null) 
      { 
       subscribers(input.Target, new PropertyChangedEventArgs(propertyName)); 
      } 

      return returnValue; 
     } 
    } 
} 

答えて

1

それは、herehereです。ティム

は、いくつかのIL織りが、これは簡単にすることはないだろう

Dim container As IUnityContainer = New UnityContainer() 
    container.AddNewExtension(Of Interception)() 
    container.RegisterType(Of Customer)(_ 
      New Interceptor(Of VirtualMethodInterceptor)(), _ 
      New InterceptionBehavior(Of NotifyPropertyChangedBehavior)()) 
+0

あなたのコードがコンパイルされ、一見動作しますが、期待通りにPropertyChangedイベントは、お客様により提起されていません。私はソースコードをc#に変更しました。これはポストを読む人が増えているようです。 –

+0

エラーが見つかりました。インターセプタはVirtualMethodInterceptorではなくTransparentProxyInterceptorでなければなりません。 – onof

0

VirtualMethodInterceptorを使用する必要があります。私は、PropertyChangedのNotifyPropertyChangedBehavior.Invokeチェックが追加または削除されないことを発見しました。メソッド名が一致するかどうかをチェックするように変更しています。

元のNotifyPropertyChangedBehaviorは、msdnのUnityドキュメントにあります。なぜ元のコードが動作しないのか誰にでも教えてもらえれば興味があります。

クラス定義

public class NotifyPropertyChangeClass 
    : INotifyPropertyChanged 
{ 
    public virtual int SomeInt { get; set; } 

    public virtual event PropertyChangedEventHandler PropertyChanged; 
} 

IUnityContainerセットアップ

container.AddNewExtension<Interception>(); 
container.RegisterType<NotifyPropertyChangeClass>(
    new Interceptor<VirtualMethodInterceptor>(), 
    new InterceptionBehavior(new NotifyPropertyChangedBehavior())); 

NotifyPropertyChangedBehavior修正(original

public class NotifyPropertyChangedBehavior : IInterceptionBehavior 
{ 
... 
    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 
    { 
     if (input.MethodBase.Name.Equals(addEventMethodInfo.Name))//(input.MethodBase == addEventMethodInfo) 
     { 
      return AddEventSubscription(input, getNext); 
     } 
     if (input.MethodBase.Name.Equals(removeEventMethodInfo.Name))//(input.MethodBase == removeEventMethodInfo) 
     { 
      return RemoveEventSubscription(input, getNext); 
     } 
     if (IsPropertySetter(input)) 
     { 
      return InterceptPropertySet(input, getNext); 
     } 
     return getNext()(input, getNext); 
    } 
... 
} 
関連する問題