2012-10-19 5 views
6

Wir machen eine Menge von INotifyPropertyChanged-Implementierungen in unseren View-Modellen und sind ehrlich gesagt nicht mehr in der Lage, die Eigenschaft geänderte Ereignisse in unserem Code aus Unannehmlichkeiten und ästhetischen Gründen explizit auszulösen.Hinzufügen einer Erweiterungsmethode zu Property Accessor

ich eine Erweiterung auf dem Setter unserer Eigenschaft setzen will, wie die resultierenden Code aussehen zu machen:

public string LazyAccessor 
{ 
    get; 
    set.notify(); 
} 

Gibt es eine Möglichkeit, dies zu tun? Können wir eines erfinden, wenn nicht?

Antwort

3

Extension methods können nur Typen hinzugefügt werden. Die Getter und Setter für automatische Eigenschaften werden in Methoden mit Unterstützungsvariablen vom Compiler konvertiert, so dass es keine Möglichkeit gibt, eine Erweiterungsmethode auf ihnen zu setzen.

2

Gibt es eine Möglichkeit, dies zu tun?

Nein, es gibt nicht, nicht wie Sie gepostet. Erweiterungsmethoden arbeiten auf Typen, nicht Getter oder Setter.

Können wir eines erfinden, wenn nicht?

Das würde Änderungen an der C# -Spezifikation erfordern - keine wahrscheinliche Sache.

Es gibt andere Ansätze, die Sie ergreifen können, um dies zu erleichtern - indem Sie eine Basisklasse mit einer Methode verwenden, die zum Beispiel die Kesselplatte für Sie aufruft.

+0

Ein weiterer interessanter Ansatz. Könntest du meine Antwort sehen und sehen, ob das auch machbar ist? Ich schätze deine Meinung, denn dein Ruf geht dir voraus. Vielleicht ist es zu schwer? –

0

Sie schafften es nicht in 4.0, aber es wird gerüchteweise in 5.0 aufgenommen.

Ich fand this Ansatz hilfreich.

4

Auschecken NotifyPropertyWeaver. Dadurch wird der Code während des Erstellungsprozesses geändert, damit die Eigenschaften das Muster INotifyPropertyChanged implementieren.

Dies ist als Visual Studio Extension

+0

Ich nehme an, das war entweder ein Vorläufer von AOP mit Sachen wie PostSharp oder sie wussten nicht, PostSharp existierte? –

+0

@BigM Ich bin mir nicht sicher über die Details, wie beide funktionieren. Ich weiß, dass beide IL Weaving verwenden, also sind sie ähnlich im Konzept. Der Grund, warum ich NotifyPropertyWeaver verwende, ist, dass Sie Ihren Code nicht mit Attributen überladen müssen. – cadrell0

+0

Ein guter Grund, diese Lösung zu verwenden. PostSharp ist *** sehr *** generisch und das ist geeignet, ** einen ** Schmerzpunkt zu lösen, es wird sicherlich prägnanter sein! –

0

Sie nicht, dass es sich auf dem Set tun könnte. Das ist eine Aktion. Sie könnten jedoch in der Lage sein, dies zu tun:

public static class extensions() 
{ 
    public static NotifyAccessorSet(this string value) { some code } 
} 

public class SomeClass() 
{ 
    ..... 
    private string mAccessor; 

    public string LazyAccessor{ 
    get { return mAccessor; } 
    set { mAccessor = value; mAccessor.NotifyAccessorSet(); } 
    } 

} 

Es ist etwas aus der Spitze von meinem Kopf und im Kopf behalten, dass die Extension-Methode auf alle Typen string anwenden würde, so dass Sie Ihren eigenen Rückgabetyp möchten umzusetzen und anzuwenden die Erweiterungsmethode dazu. Geben Sie diesen Typ dann von lazyaccessor zurück.

+0

Ich bin mir nicht sicher, aber ich denke, NotifyPropertyEvent auslösen müssen Sie das Ursprungsobjekt (Absender) und Eigenschaftsname ("LazyAccessor" in diesem Beispiel) wissen. Dein Code macht es noch gesprächiger. – Ondra

+0

Sie hätten das Ursprungsobjekt ... es wäre der "Wert" in der Funktion NotifyAccessorSet. Auf jeden Fall ... nur ein Vorschlag. Dieser Ansatz würde einen zusätzlichen Funktionsaufruf implementieren, der nur eine Möglichkeit bietet, die Benachrichtigung in der set-Methode zu implementieren. – DRobertE

0

Sie können ein "eigenschaftsähnliches" Verhalten emulieren, ohne das Ereignis manuell aufzurufen, indem Sie die Konvertierungsoperatoren einer benutzerdefinierten generischen Struktur überschreiben. Das Folgende ist meine Lösung:

public struct column<TType> 
{ 
    private TType _value; 

    private column(TType value) : this() 
    { 
     _value = value; 
    } 

    private void Set(TType value) 
    { 
     // Implement your custom set-behavior... 
    } 

    private TType Get() 
    { 
     // Implement your custom get-behavior... 
     return _value; 
    } 

    public override string ToString() 
    { 
     return _value.ToString(); 
    } 

    public static implicit operator column<TType>(TType p) 
    { 
     column<TType> column = new column<TType>(p); 
     column.Set(p); 
     return column; 
    } 

    public static implicit operator TType(column<TType> p) 
    { 
     return p.Get(); 
    } 
} 

ich die Struktur mit einem generischen Parameter deklarieren von Konvertierungsfehler zu vermeiden. Sie können es wie folgt verwenden:

public class Test 
{ 
    public column<int> kKey; 

    public column<float> dMoney; 

    public column<string> cValue; 


    public Test() 
    { 
     kKey = 42; 
     dMoney = 3.1415926f; 
     cValue = "May the force be with you!"; 
    } 
} 

... Ich weiß, die Frage ist veraltet, aber es kann jemand in der Zukunft helfen.