2010-03-07 6 views
6

Ich habe vor kurzem begonnen, mit PostSharp zu experimentieren, und ich fand einen besonders hilfreichen Aspekt zur Automatisierung der Implementierung von INotifyPropertyChanged. Sie können das Beispiel here sehen. Die grundlegende Funktionalität ist hervorragend (alle Eigenschaften werden benachrichtigt), aber es gibt Fälle, in denen ich die Benachrichtigung unterdrücken möchte.Unterdrücken von PostSharp Multicast mit Attribut

Zum Beispiel könnte ich wissen, dass eine bestimmte Eigenschaft einmal im Konstruktor festgelegt ist und sich nie wieder ändern wird. Daher muss der Code für NotifyPropertyChanged nicht ausgegeben werden. Der Aufwand ist minimal, wenn Klassen nicht häufig instanziiert werden, und ich kann das Problem verhindern, indem ich von einer automatisch generierten Eigenschaft auf eine Feld-unterstützte Eigenschaft umschalte und in das Feld schreibe. Wenn ich jedoch dieses neue Tool lerne, wäre es hilfreich zu wissen, ob es eine Möglichkeit gibt, eine Eigenschaft mit einem Attribut zu versehen, um die Codegenerierung zu unterdrücken. Ich möchte in der Lage sein, so etwas zu tun:

[NotifyPropertyChanged] 
public class MyClass 
{ 
    public double SomeValue { get; set; } 

    public double ModifiedValue { get; private set; } 

    [SuppressNotify] 
    public double OnlySetOnce { get; private set; } 

    public MyClass() 
    { 
     OnlySetOnce = 1.0; 
    } 
} 

Antwort

5

Sie können eine MethodPointcut anstelle eines MulticastPointcut, das heißt verwenden Linq-over-Reflexion und Filter gegen PropertyInfo.IsDefined (Ihr Attribut).

private IEnumerable<PropertyInfo> SelectProperties(Type type) 
    { 
     const BindingFlags bindingFlags = BindingFlags.Instance | 
      BindingFlags.DeclaredOnly 
              | BindingFlags.Public; 

     return from property 
        in type.GetProperties(bindingFlags) 
       where property.CanWrite && 
        !property.IsDefined(typeof(SuppressNotify)) 
       select property; 
    } 

    [OnLocationSetValueAdvice, MethodPointcut("SelectProperties")] 
    public void OnSetValue(LocationInterceptionArgs args) 
    { 
     if (args.Value != args.GetCurrentValue()) 
     { 
      args.ProceedSetValue(); 

      this.OnPropertyChangedMethod.Invoke(null); 
     } 
    } 
+0

Ausgezeichnet, danke. Dies ist ein sehr leistungsfähiges Werkzeug und mein Projekt fühlt sich deutlich sauberer ohne all die lästigen INotifyPropertyChanged Sanitär. –

0

FYI, ich hatte einige Probleme mit dem Beispiel auf der Sharpcrafters Website und hatte die folgende Änderung vornehmen:

/// <summary> 
    /// Field bound at runtime to a delegate of the method <c>OnPropertyChanged</c>. 
    /// </summary> 
    [ImportMember("OnPropertyChanged", IsRequired = true, Order = ImportMemberOrder.AfterIntroductions)] 
    public Action<string> OnPropertyChangedMethod; 

Ich glaube, es war das OnPropertyChanged Mitglied einzuführen, sondern importiert, bevor er eine hatte Chance geschaffen zu werden. Dies würde dazu führen, dass das OnPropertySet fehlschlägt, weil this.OnPropertyChangedMethod null ist.

3

Eine weitere einfache Methode verwenden:

[NotifyPropertyChanged(AttributeExclude=true)] 

... die Attribute für eine bestimmte Methode zu unterdrücken. Dies funktioniert auch dann, wenn der Klasse ein globales Attribut zugeordnet ist (wie im obigen Beispiel).

Hier ist der vollständige Beispielcode:

[NotifyPropertyChanged] 
public class MyClass 
{ 
    public double SomeValue { get; set; } 

    public double ModifiedValue { get; private set; } 

    [NotifyPropertyChanged(AttributeExclude=True)] 
    public double OnlySetOnce { get; private set; } 

    public MyClass() 
    { 
     OnlySetOnce = 1.0; 
    } 
} 

Sobald Sie diese Zeile hinzufügen, Postsharp wird sogar den MSVS GUI aktualisieren, um die unterstrichenen entfernen angibt, welche das Verfahren gebunden sind Attribute. Wenn Sie den Debugger ausführen, wird natürlich die Ausführung von Attributen für diese bestimmte Methode übersprungen.

Verwandte Themen