设计模式-InotifyPropertyChanged



我有一个名为IMailSender和ISMSSender的接口。我有一个抽象类叫Device。

Device1继承自设备IMailSenderDevice2继承自Device、IMailSender、ISMSSender

我希望IMailSender的所有字段都调用notifypropertychanged。我是否也必须在Device1中实现所有IMailSender属性才能调用notifypropertychanged并在Device2中执行相同的代码,或者有更好的解决方案?

谢谢。

您的类必须引发PropertyChanged事件,因为接口只能确保所有实现类都有一个返回类型相同的方法。一个好的方法是定义一个基类(这是MVVM模式中非常常见的方法,例如MVVM Light框架),该基类通过一个方法引发事件,所有其他适当的类都可以从该方法继承。例如:

...
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");
        }
    }
    ...
}

其他解决方案是面向方面的。例如postsharp。shttp://www.sharpcrafters.com/solutions/notifypropertychanged

因此,可以在属性上放置PropertyChanged属性。

同样使用.net 4.5,您可以使用CallerInfoAttribute来实现一个不需要属性名称的简单实现,例如:

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));
        }
    }

有了它,你就可以在没有任何参数的情况下调用该方法

public int MyProperty
{
  get
   {
   ...
   }
    set
    {
        m_MyProperty=value;
        OnPropertyChanged();
    }
}

使用this,调用ObservableFactory.Create()并使用返回对象。要使用通知事件,只需将其强制转换为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;
        }
    }

相关内容

  • 没有找到相关文章

最新更新