Reiner Code unter der Flagge von AOP und dem verhassten #WarningReal EstateChanged

    Nachdem Sie der allgemeinen Hysterie am Hub erlegen sind

    ("Ich warne, die Immobilie hat sich geändert" übersetzt Googles geliebtes "Ich benachrichtige die geänderte Immobilie"), werden Sie über die Änderungsmeldungen informiert. Ich beschloss zu untersuchen, wie weit die Menschheit mit der Erfindung von Fahrrädern gekommen ist.

    OnPropertyChanged ("Property")
    OnPropertyChanged (() => Property)
    SetProperty (ref storage, value)
    [CallerMemberName]
    [Magic]
    AOPs mit verschiedenen Stripes
    bieten sogar roslyn.codeplex.com/discussions/550266, warum nicht.
    Dennoch ist nameof (Eigentum) das Beste - vorsichtig si sharpe 6.
    Die Konsequenzen der Hysterie werden in den folgenden Werken
    ausgedrückt habrahabr.ru/post/199378
    habrahabr.ru/post/246469
    habrahabr.ru/post/95211
    Ich persönlich mag OnPropertyChanged (nameof (Property)) und OnPropertyChanged (() => Property) , die erste Option funktioniert schneller.
    Am häufigsten verwende ich jedoch SetProperty (ref storage, value) , eine Box-Version von BindableBase .
    Scrooge2 Gerüst gepostet
    Hör auf, Fahrräder zu erfinden.
    Verwenden Sie die üblichen INotifyPropertyChanged Hände fallen nicht weg, aber ohne.

    Ich unterstütze voll und ganz, aber ... NEIN.
    Nun, Feile und Vorschlaghammer.
    Ich bin für sauberen Code! Protokollieren, Ausnahmen abfangen, Zugriffsrechte überprüfen, alle Arten von Benachrichtigungen usw. - rauchen Sie den Code. Das alte Wissen der Proxy-Vorlage, zum Beispiel habrahabr.ru/post/88722 , ermöglicht es Ihnen, den Code zu bereinigen .
    Ich werde mein Leben verkomplizieren und Klassen und keine Schnittstellen verwenden.
    public class Data
        {
            public virtual int Value { get; set; }
            public virtual string Source { get; set; }
        }
    

    Benachrichtigungen, nichts persönliches
    class BindableObject : BindableBase
        {
            public new bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null)
            {
                return base.SetProperty(ref storage, value, propertyName);
            }
        }
    

    Und der Stellvertreter selbst, der die ganze Drecksarbeit übernommen hat
    public class ProxyData : Data, INotifyPropertyChanged
        {
            Data _target;
            BindableObject _notifier;
            public ProxyData(Data target)
            {
                _target = target;
                _notifier = new BindableObject();
            }
            public override int Value
            {
                set
                {
                    int newValue = 0;
                    if (_notifier.SetProperty(ref newValue, value))
                        base.Value = newValue;
                }
            }
            public override string Source
            {
                set
                {
                    string newSource = null;
                    if (_notifier.SetProperty(ref newSource, value))
                        base.Source = newSource;
                }
            }
            public event PropertyChangedEventHandler PropertyChanged
            {
                add { _notifier.PropertyChanged += value; }
                remove { _notifier.PropertyChanged -= value; }
            }
        }
    

    Ich erstelle eine Konsolenanwendung, in der ich überprüfen kann, ob sie nicht in der Konsole enthalten ist. Ich warne Sie, dass sich die Immobilie geändert hat
    data = new ProxyData(new Data());
    (data as INotifyPropertyChanged).PropertyChanged += (s, e) => { Console.WriteLine(string.Format("Property {0} changed!", e.PropertyName)); };
    data.Value = 10;
    data.Source = "List";
    

    Vorteile : Die reinste Datenklasse. Alles ist einfach und klar. Sie können eine Reihe verschiedener Proxy-Logger, Zugriff usw. erstellen, verschiedene Funktionen kombinieren, sicher löschen und hinzufügen, die nicht mit dem sofortigen Betrieb der Anwendung zusammenhängen.
    Nachteile : Es ist nutzlos, ich habe das Ansichtsmodell fast in ein Modell verwandelt, nachdem ich einen weiteren Link der Vorlage -> ViewModel -> Proxy -> Ansichtsvorlage erhalten habe. Einer der Zwecke des ViewModel ist die Benachrichtigung. Natürlich können Sie die Datenvorbereitung in vm belassen. Außerdem ist der gesamte Code geworden noch mehr, obwohl es so aussieht, als ob die verantwortung von vm abgenommen hat, oh solid SOLID.
    Hysterie! AOP-Zeit ist gekommen, es wurde eine ganze Menge über AOP geschrieben, und ich werde mich nicht mit der Theorie befassen.
    Ich arbeite mit IUnityContainerweil es kann als verpackt betrachtet werden, interagiert gut mit Prisma .
    Und hier ist das universelle Verhalten des Notifizierenden, Horror
    class NotifyPropertyChangedBehavior : IInterceptionBehavior, INotifyPropertyChanged
        {
            static readonly MethodBase _add;
            static readonly MethodBase _remove;
            static NotifyPropertyChangedBehavior()
            {
                var methods = typeof(INotifyPropertyChanged).GetMethods();
                _add = methods[0];
                _remove = methods[1];
            }
            public IEnumerable GetRequiredInterfaces()
            {
                return Type.EmptyTypes;
            }
            public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
            {
                IMethodReturn result = null;
                if (IsPropertyChanged(input))
                    if (SubscribeUnsubscribe(input))
                        result = input.CreateMethodReturn(null);
                    else
                    {
                        PropertyInfo property;
                        if (IsSetMethodCalled(out property, input))
                            result = SetValue(property, input, getNext);
                    } 
                return result ?? getNext()(input, getNext);
            }
            public bool WillExecute
            {
                get { return true; }
            }
            public event PropertyChangedEventHandler PropertyChanged;
            /// 
            /// Проверка вызова мутатора
            /// 
            /// 
            bool IsSetMethodCalled(out PropertyInfo property, IMethodInvocation input)
            {
                string propertyName = input.MethodBase.Name.TrimStart("set_".ToArray());
                property = input.Target.GetType().GetProperty(propertyName);
                return property != null;
            }
            /// 
            /// Установить 
            /// 
            /// 
            IMethodReturn SetValue(PropertyInfo property, IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
            {
                var oldValue = property.GetValue(input.Target, new object[0]);
                var newValue = input.Arguments[0];
                IMethodReturn result = null;
                //обновление только если пришло действительно новое значение
                if (!Equals(oldValue, newValue))
                {
                    result = getNext()(input, getNext);
                    if (PropertyChanged != null)
                        PropertyChanged(input.Target, new PropertyChangedEventArgs(property.Name));
                }
                else result = input.CreateMethodReturn(null);            
                return result;
            }
            /// 
            /// Проверка вызова методов INotifyPropertyChanged
            /// 
            bool SubscribeUnsubscribe(IMethodInvocation input)
            {
                if (input.MethodBase == _add)
                {
                    PropertyChanged += (PropertyChangedEventHandler)input.Arguments[0];
                    return true;
                }
                else if (input.MethodBase == _remove)
                {
                    PropertyChanged -= (PropertyChangedEventHandler)input.Arguments[0];
                    return true;
                }
                return false;
            }
            /// 
            /// Вызов на экземпляре реализующим INotifyPropertyChanged
            /// 
            bool IsPropertyChanged(IMethodInvocation input) { return input.Target is INotifyPropertyChanged; }
        }
    

    gut, und ein Stück Code, wo alles verbindet
    IUnityContainer container = new UnityContainer();
    container.AddNewExtension();
    container.RegisterType(new Interceptor(),
                    new InterceptionBehavior()
                    , new AdditionalInterface());
    var data = container.Resolve();
    (data as INotifyPropertyChanged).PropertyChanged += (s, e) => { Console.WriteLine(string.Format("Property {0} changed!", e.PropertyName)); };
    data.Value = 10;
    data.Source = "List";
    data.Value = 10;
    Console.ReadKey();
    

    Ergebnis ----->
    Bild
    Brötchen für die besonders Faulen
    public static class Extensions
        {
            public static IUnityContainer RegisterViewModel(this IUnityContainer container) where T : class
            {
                container.AddNewExtension();
                return container.RegisterType(new Interceptor(),
                    new InterceptionBehavior()
                    , new AdditionalInterface());
            }
        }
    

    Minimierung der Registrierung
    container.RegisterViewModel();
    

    Sie können keine Illusionen hinterlassen, die Basis ist dieselbe STELLVERTRETUNG, nur wir wissen nichts über ihn.
    Vorteile : Jetzt können Sie eine VM aus allem erstellen, was über virtuelle Eigenschaften, vollständige Codeminimierung, eine saubere Klasse verfügt, ohne dass ich Sie vor einer Änderung von Real Estate, allerlei Attributen und ähnlichen technischen Details warne.
    Nachteile : Es ist überhaupt nicht einfach, Sie müssen den Behälter und seine Fähigkeiten verstehen, Nicht-Manifestation in seiner reinen Form, wahrgenommen als Magie, viel Reflexion - dies ist nichts für schwache Nerven, die Leistung sichten.
    Nachdem ich ein kleines Experiment mit Mitarbeitern durchgeführt hatte, war das Ergebnis bedauerlich. Die Programmierer hatten große Schmerzen, als ich sie bat, herauszufinden, wie es funktioniert.
    Aber es funktioniert.
    Im Allgemeinen haben sie es nicht vorgestellt und es fast dem gerechten Feuer gegeben, aber das ist cool, aber alles hängt von der Ebene des Teams und ihrem Wunsch nach Schwierigkeiten ab.

    PS Ich empfehle OnPropertyChanged (nameof (Property)) allen, die Angst vor dieser Dose haben - optimal für alle Indikatoren, außer dass sie mit HANDS geschrieben werden muss . Boo!

    Jetzt auch beliebt: