2010-12-01 4 views
3

Ich entwickle viele Ansicht Modelle, die sind:Welche Art von Compiler Magie brauchen wir mehr?

1) Alle müssen implementieren INotifyPropertyChanged, um bindbar zu UI.

2) Property Setter müssen PropertyChanged bei Änderung erhöhen.

3) Das PropertyChanged-Ereignis muss den richtigen Eigenschaftsnamen angeben.

Wenn Sie (wie ich) gebunden so etwas wie dieses zu schreiben:


public string Name 
{ 
    get 
    { 
    return _name; 
    } 
    set 
    { 
    if (_name != value) 
    { 
     _name = value; 
     RaisePropertyChanged("Name"); 
    } 
    } 
} 

dann wie folgt diese Methode Refactoring und manchmal vergessen, Eigenschaftsnamen zu aktualisieren wörtliche:


string _fundName; 
public string FundName 
{ 
    get 
    { 
    return _fundName; 
    } 
    set 
    { 
    if (_fundName != value) 
    { 
     _fundName = value; 
     RaisePropertyChanged("Name"); 
    } 
    } 
} 

Und dann ein verbringen Tag zu debuggen, warum Ihre Benutzeroberfläche nicht aktualisiert und Datenbindung funktioniert nicht ordnungsgemäß.

Dann brauchen wir nur eine Art Magie.

Was passiert, wenn ich brauche nur zu schreiben:


[Magic] // implicit transformation 
public string FundName { get; set; } 

oder wenn ich viele Eigenschaften haben:


[Magic] 
public class MyViewModel 
{ 
    public string FundName { get; set; } 
    public string FundType { get; set; } 

    [NoMagic] // suppress transformation 
    public int InternalId { get; set; } 
} 

So habe ich entwickelt gerade eine MSBuild Aufgabe, diese Magie nach dem Build zu tun (http://kindofmagic.codeplex.com).

Die Frage ist, welche Art von magischer Nachbearbeitung möchten Sie mehr?

Ist die automatische Implementierung von INotifyPropertyChanging sinnvoll?

+0

Was ist mit dem Erstellen der gleichen Sache für INotifyPropertyChanging? –

+0

@CommanderZ Implementieren und verwenden Sie INotifyPropertyChanging? Wenn ja wofür? vielleicht möchten Sie http://stackoverflow.com/questions/3835788/other-than-linq-to-sql-does-anything-else-consume-inotifypropertyychanging kommentieren – Simon

Antwort

1

Wenn wir phantastische Code-Generierung haben, würde ich mir einen Weg wünschen, DependancyProperties leichter zu generieren. Der Snippit, den ich benutze, ist sicherlich hilfreich, aber ich bin kein Fan, wie durcheinander der Code aussieht, wenn Sie On-Change- und Coerce-Callbacks und Metadaten-Optionen haben. Vielleicht werde ich versuchen, eine Probe nach der Arbeit nachzuahmen.

Bearbeiten: Nun, hier ist ein Konzept. Es würde viel geschickter aussehen, wenn Sie anonyme Methoden an Attribute übergeben, aber es ist immer noch ein Schritt nach oben.

Vorher:

[DpDefault("The Void")] 
[DpCoerce(new CoerceValueCallback(MainWindow.CoerceAddress))] 
[DpChanged(new PropertyChangedCallback(MainWindow.ChangeAddress1))] 
[DpChanged(new PropertyChangedCallback(MainWindow.ChangeAddress2))] 
[DpOptions(FrameworkPropertyMetadataOptions.Inherits)] 
public string Address { 
    get { return Dp.Get<string>(); } 
    set { 
     if (Dp.Get<string>() != value) { 
      Dp.Set(value); 
      PostOffice.SendMailToTheBoss("I moved!"); 
     } 
    } 
} 

Nach:

public string Address { 
    get { return (string)GetValue(AddressProperty); } 
    set { 
     if ((string)GetValue(AddressProperty) != value) { 
      SetValue(AddressProperty, value); 
      PostOffice.SendMailToTheBoss("I moved!"); 
     } 
    } 
} 

public static readonly DependencyProperty AddressProperty = 
    DependencyProperty.Register("Address", typeof(string), typeof(MainWindow), 
     new FrameworkPropertyMetadata((string)"The Void", 
      FrameworkPropertyMetadataOptions.Inherits, 
      new PropertyChangedCallback(MainWindow.ChangeAddress1) 
       + new PropertyChangedCallback(MainWindow.ChangeAddress2), 
      new CoerceValueCallback(MainWindow.CoerceAddress))); 

Typischerweise nur die 'DpDefault' Attribut würde verwendet werden, aber auch wenn es nicht der Code kürzer macht, macht es sicherlich es klarer. Hier wäre ein typisches Beispiel:

Vorher:

[DpDefault("The Void")] 
public string Address { get; set; } 

Nach:

public string Address { 
    get { return (string)GetValue(AddressProperty); } 
    set { SetValue(AddressProperty, value); } 
} 

public static readonly DependencyProperty AddressProperty = 
    DependencyProperty.Register("Address", typeof(string), typeof(MainWindow), 
     new UIPropertyMetadata((string)"The Void")); 
+0

Gute Idee. Wir können die Abhängigkeitseigenschaft von der normalen erzeugen, indem wir den Setter im OnDependencyPropertyChanged-Handler extrahieren. Und generiere DependencyProperty static readonly field mit dem korrekt abgeleiteten Namen, falls dieser nicht existiert. –

+0

Bearbeitete die Antwort mit einem Mock-up-Konzept, wie die Code-Transformation aussehen könnte. – YotaXP

0

Etwas, das Ihr Leben ein wenig leichter machen könnte, ist dies ... (Ich habe es von Caliburn Micro abgeholt).

public virtual void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property) { 
      NotifyOfPropertyChange(property.GetMemberInfo().Name); 
     } 

Dies ermöglicht Ihnen, die folgenden ..

NotifyOfProperyChange (() => this.PropertyName) zu tun;

Dadurch werden Probleme mit dem Code zur Entwurfszeit und nicht zur Laufzeit hervorgehoben.

Caliburn Micro ist ein geniales kleines Framework, das Sie sich anschauen sollten, es entfernt so viel von der Verdrahtung, die mit MVVM und Silverlight/WPF verbunden ist!

+0

Ich habe C.M auch verwendet.Aber, ehrlich gesagt, das ist eine Menge verschwendeter CPU-Zyklen, nur um einen RICHTIGEN Namen der Eigenschaft zu erhalten. Der Hauptgrund für das KindOfMagic-Projekt besteht darin, es so leistungsfähig wie möglich zu machen und das Tippen für Benutzer so wenig wie möglich zu machen. –

1

"Magie" ist fast immer ein schrecklicher Name für Methode oder Eigenschaft oder Variable in jeder Sprache. Sie sollten das Attribut in etwas beschreibenderes umbenennen. Stellen Sie sich vor, Sie sind nur ein zufälliger Internet-Fußgänger und stolpern über einen Stückcode mit dem Attribut "Magic", was sagt es Ihnen über den Code? Genau nichts :)

Ich werde versuchen, Ihren Code sowieso, es hat Potenzial, eine ziemliche Zeit zu sparen. Dies sollte definitiv ein Teil von .NET sein.

+0

Attribut namens Magic, würde auf jeden Fall meine Aufmerksamkeit kaufen. Aber ich stimme dir zu. Auf der Suche nach einem besseren Namen, irgendwelche Ideen? –

+0

Ich denke, NotifyPropertyChanged würde gut funktionieren. –

+0

Das ist nicht wirklich eine Antwort. – Simon

0

Dies kann bereits mit einem AOP (Aspect Oriented Programming) Werkzeug wie PostSharp: http://www.richard-banks.org/2009/02/aspect-oriented-programming.html (mit v1.x) http://www.sharpcrafters.com/solutions/ui#data-binding (mit v2.0)

Ich benutzte Postsharp INPC in wenigen Projekten zu implementieren und es funktionierte ziemlich gut aus, ist der Code viel sauberer und wartbar (es fügt ein paar Sekunden Zeit zu kompilieren)

+0

Ich habe PostSharp für INPC vor einem Monat versucht, aber IL-Code für Setter erzeugt wurde so aufgebläht und hässlich (ich habe Reflector verwendet). Meine Meinung ist, dass generische AOP-Tools einen zu großen Overhead für dieses kleine spezielle Problem einführen. –

+0

Haben Sie diese Meinung mit irgendeiner Leistungsprüfung bestätigt? Nach meiner Erfahrung ist der von AOP in diesem Fall eingeführte Overhead nicht wahrnehmbar. –

+1

Postsharp Bloat es injiziert ca. 150 Zeilen Code in jede Eigenschaft. – Simon

4

Versuchen Sie, diese

http://code.google.com/p/notifypropertyweaver/

  • keine Attribute erforderlich
  • Keine Referenzen erforderlich
  • keine Basisklasse
  • erforderlich

hier darüber

meinem Blog Artikel ist

http://codesimonsays.blogspot.com/2010/11/attempting-to-solve-inotifypropertychan.html

Es Attribute unterstützt Sie

  • NotifyPropertyAttribute anfordern (benachrichtigen für eine Eigenschaft)
  • NotifyForAllAttribute (für alle Objekte auf einer Art benachrichtigen)
  • NotifyIgnoreAttribute
  • AlsoNotifyFor (von benachrichtigen Code ermöglicht die Injektion, die auf eine andere Eigenschaft Punkte) (nicht für eine Eigenschaft oder Art mitteilen)

Obwohl diese Optionen und zur Feinabstimmung vorgesehen sind. Die meisten Injektionen werden konventionell durch Analyse der vorhandenen IL durchgeführt.

+0

Warum habe ich Sie vor einem Tag nicht gefunden? Ich würde nicht meins starten ... –

+0

Wahrscheinlich wegen Alien-Projekt-Hosting;) –

+0

Btw, wie die Idee mit Verweis Entfernung. Ich kam nur um Entfernung zu entfernen;) –