0

IMailSender と ISMSSender というインターフェースがあります。Device という抽象クラスがあります。

Device1 は Device、IMailSender から継承します Device2 は Device、IMailSender、ISMSSender から継承します

IMailSender のすべてのフィールドで、notifypropertychanged を呼び出す必要があります。デバイス 1 にもすべての IMailSender プロパティを実装して、notifypropertychanged を呼び出し、デバイス 2 で同じコードを実行する必要がありますか、それともより良い解決策がありますか?

ありがとう。

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

別のソリューションは、アスペクト指向です。たとえば、ポストシャープを使用します。秒。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 に答える