2013-02-11 72 views
0

我有一個名爲IMailSender和ISMSSender的接口。 我有一個名爲Device的抽象類。InotifyPropertyChanged

Device1的從設備繼承,IMailSender 設備2從設備繼承,IMailSender,ISMSSender

我想IMailSender的各個領域調用notifypropertychanged。 我是否還必須在Device1中實現所有IMailSender屬性才能調用notifypropertychanged並在Device2中執行相同的代碼,或者有更好的解決方案?

謝謝。

回答

0

您的課程必須提高PropertyChanged事件,因爲該接口只會確保所有實施類具有相同返回類型的方法。一個好的方法是定義一個基類(這是MVVM模式的一種非常常見的方法,例如MVVM Light框架),它通過一個方法來引發事件,所有其他適當的類可以繼承該方法。 E.g:如下

... 
public abstract class BaseViewModel : IMailSender, INotifyPropertyChanged 
{ 
    ... 
    public void RaisePropertyChanged(string property) 
    { 
     if (property != null) 
     { 
      PropertyChanged(property); 
     } 
    } 
} 

繼承類可以使用這個:

... 
public class AViewModel : BaseViewModel 
{ 
    ... 
    private string _property; 
    public string Property 
    { 
     get 
     { 
      return _property; 
     } 
     set 
     { 
      _property = value; 
      RaisePropertyChanged("Property"); 
     } 
    } 
    ... 
} 
0

的其他解決辦法是看點Orientied。例如與postsharp。 s。 http://www.sharpcrafters.com/solutions/notifypropertychanged

所以你可以在屬性上放置一個PropertyChanged屬性。

還與.NET 4.5,你可以使用CallerInfoAttribute做一個簡單的實現,並不需要例如PROPERTYNAME看到:

http://danrigby.com/2012/04/01/inotifypropertychanged-the-net-4-5-way-revisited/ - >

protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     var eventHandler = this.PropertyChanged; 
     if (eventHandler != null) 
     { 
      eventHandler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

與您可以撥打沒有任何parametr

public int MyProperty 
{ 
    get 
    { 
    ... 
    } 

    set 
    { 
     m_MyProperty=value; 
     OnPropertyChanged(); 
    } 
} 
0

使用這種方法,調用ObservableFactory.Create(),並用返回OB JECT。要使用通知事件,只需將其投射到INotifyPropertyChanged

public static class ObservableFactory 
    { 
     public static T Create<T>(T target) 
     { 
      if (!typeof(T).IsInterface) 
       throw new ArgumentException("Target should be an interface", "target"); 

      var proxy = new Observable<T>(target); 
      return (T)proxy.GetTransparentProxy(); 
     } 
    } 

    internal class Observable<T> : RealProxy, INotifyPropertyChanged, INotifyPropertyChanging 
    { 
     private readonly T target; 

     internal Observable(T target) 
      : base(ImplementINotify(typeof(T))) 
     { 
      this.target = target; 
     } 

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

      if (methodCall != null) 
      { 
       return HandleMethodCall(methodCall); 
      } 

      return null; 
     } 

     public event PropertyChangingEventHandler PropertyChanging; 
     public event PropertyChangedEventHandler PropertyChanged; 



     IMessage HandleMethodCall(IMethodCallMessage methodCall) 
     { 
      var isPropertySetterCall = methodCall.MethodName.StartsWith("set_"); 
      var propertyName = isPropertySetterCall ? methodCall.MethodName.Substring(4) : null; 

      if (isPropertySetterCall) 
      { 
       OnPropertyChanging(propertyName); 
      } 

      try 
      { 
       object methodCalltarget = target; 

       if (methodCall.MethodName == "add_PropertyChanged" || methodCall.MethodName == "remove_PropertyChanged"|| 
        methodCall.MethodName == "add_PropertyChanging" || methodCall.MethodName == "remove_PropertyChanging") 
       { 
        methodCalltarget = this; 
       } 

       var result = methodCall.MethodBase.Invoke(methodCalltarget, methodCall.InArgs); 

       if (isPropertySetterCall) 
       { 
        OnPropertyChanged(methodCall.MethodName.Substring(4)); 
       } 

       return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall); 
      } 
      catch (TargetInvocationException invocationException) 
      { 
       var exception = invocationException.InnerException; 
       return new ReturnMessage(exception, methodCall); 
      } 
     } 

     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      var handler = PropertyChanged; 
      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 

     protected virtual void OnPropertyChanging(string propertyName) 
     { 
      var handler = PropertyChanging; 
      if (handler != null) handler(this, new PropertyChangingEventArgs(propertyName)); 
     } 

     public static Type ImplementINotify(Type objectType) 
     { 
      var tempAssemblyName = new AssemblyName(Guid.NewGuid().ToString()); 

      var dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
       tempAssemblyName, AssemblyBuilderAccess.RunAndCollect); 

      var moduleBuilder = dynamicAssembly.DefineDynamicModule(
       tempAssemblyName.Name, 
       tempAssemblyName + ".dll"); 

      var typeBuilder = moduleBuilder.DefineType(
       objectType.FullName, TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract); 

      typeBuilder.AddInterfaceImplementation(objectType); 
      typeBuilder.AddInterfaceImplementation(typeof(INotifyPropertyChanged)); 
      typeBuilder.AddInterfaceImplementation(typeof(INotifyPropertyChanging)); 
      var newType = typeBuilder.CreateType(); 
      return newType; 
     } 
    }