0

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

Device1 继承自 Device、IMailSender Device2 继承自 Device、IMailSender、ISMSSender

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

谢谢。

4

3 回答 3

0

您的类必须引发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");
        }
    }
    ...
}
于 2013-02-18T11:08:34.610 回答
0

另一种解决方案是面向方面。例如使用 postsharp。s。http://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();
    }
}
于 2013-02-18T13:27:38.870 回答
0

使用它,调用 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;
        }
    }
于 2014-03-15T16:12:06.003 回答