INotifyPropertyChanged in .NET automatisch implementieren

INotifyPropertyChanged in .NET automatisch implementieren
INotifyPropertyChanged in .NET automatisch implementieren

Kennst Du das auch: Du sitzt vor Deinen .NET Klassen und musst für WPF und Co. die INotifyPropertyChanged-Schnittstelle das gefühlte tausendste Mal implementieren? Eigentlich hättest Du Besseres zu tun und der Kunde (oder Dein Chef) sitzt Dir schon im Nacken? Damit ist nun Schluss – also mit dem repetitiven implementieren der Schnittstelle –, denn dafür gibt es Abhilfe!

Installiere dazu einfach die beiden NuGet-Pakete „PropertyChanged.Fody“ und „Fody“. Konfiguriere Diese mit einer passenden „FodyWeavers.xml“-Datei und erstelle eine Klasse, Welche die INotifyPropertyChange-Schnittstelle implementiert, fertig!

Keine Lust auf „Monkey Work“ – Hilfe muss her!

Jeder .NET Entwickler, Welcher mit Daten und dessen Änderungen in Verbindung kommt, kennt es. Man muss der grafischen Oberfläche „Hey, der Vorname hier, der hat sich geändert, bitte zeige Den einmal aktualisiert an!“, mitteilen. Für gewöhnlich passiert das im .NET-Umfeld über die INotifyPropertyChanged-Schnittstelle. Diese kann nicht wirklich viel – wie auch als Interface –, Sie gibt uns jedoch den Schlachtplan für genau diese Frage: „Welche Eigenschaft hat sich geändert?“.

Wie oben schon erwähnt kann es aber nun ziemlich langweilig und vor Allem nervig werden. Schließlich besteht unsere Anwendung für gewöhnlich aus zig Klassen, Welche alle gewisse Daten beinhalten, dessen Änderungen nach außen mitgeteilt werden möchten. Tun wir dies nicht, bekommt die grafische Oberfläche davon nichts mit und kann die aktualisierten Daten auch nicht anzeigen.

Uns bleibt also nichts Anderes übrig, als die Schnittstelle in jeder benötigten Klasse zu implementieren, oder? Zum Glück ist dem nicht so! Wie das funktioniert, erfährst Du im weiteren Verlauf.

Im Videoformat

Möchtest Du etwas auf die Augen und die Ohren bekommen? Ist Dir der Text eventuell zu träge? Dann schaue Dir gerne das passende Video auf meinem YouTube-Kanal an. Beachte, dass das deutsche Video VB.NET als Sprache verwendet, allerdings ist dies natürlich genauso gut auf C# anwendbar. Ich empfehle Dir trotzdem, den Beitrag ebenso anzuschauen, da ich hier nochmal in mehr Detail auf die einzelnen Dinge eingehen kann.

Einfacher, ja, aber „ich dachte da ist mehr drin“

Wenn Du meinen detaillierten Beitrag über die INotifyPropertyChanged-Schnittstelle gelesen / gesehen hast, kennst Du vermutlich schon eine Vereinfachung. Diese haben wir erreicht, indem wir eine mehr oder weniger generischere Variante geschrieben haben. Dort gab es eine gewisse Methode (NotifyOfPropertyChange) innerhalb einer Klasse, Welche den Namen der geänderten Eigenschaft entgegengenommen hat. Das hat uns zumindest das Auslösen des „PropertyChanged“-Ereignisses vereinfacht.

Das Tolle daran war auch, dass wir den Namen der geänderten Eigenschaft nicht manuell angeben mussten. Dies konnte durch das „CallerMemberName“-Attribut des übergebenen Parameters automatisch bestimmt werden – insofern die Methode aus dem Setter der Eigenschaft aufgerufen wurde. Wenn man dann noch den „NameOf“-Ausdruck verwendet, hat man schon eine wirklich solide Basis.

Letztendlich stinkt es einem dennoch, wenn man folgenden Code sieht, Dieser ist einfach nur repetitiv und somit nicht gerade DRY getreu. Ebenso bläht er den Code unnötig auf und man hat fast gar keine Lust mehr, Diesen zu lesen. Das ist natürlich fatal..

 Public Class SomeThing
    Inherits PropertyChangedBase

    Private _company As String

    Public Property Company As String
        Get
            Return _company
        End Get
        Set(value As String)
            If _company = value Then
                Return
            End If
            _company = value
            NotifyOfPropertyChange()
        End Set
    End Property

    ' property 2...

    ' property 3...

    ' ...

End Class
public class SomeThing : PropertyChangedBase
{
    private string _company;

    public string Company
    {
        get => _company;
        set
        {
            if (_company == value)
                return;
            _company = value;
            NotifyOfPropertyChange();
        }
    }

    // property 2...

    // property 3...

    // ...

}

Fody installieren

Das NuGet-Paket des Vertrauens, Welches uns die Arbeit erleichtern wird, nennt sich „Fody“. Also zumindest das Haupt-Paket, zusätzlich brauchen wir ein Sub-Paket namens „PropertyChanged.Fody“. Installiere nun also bitte beide Pakete, indem Du entweder die grafische Oberfläche des NuGet Paket-Managers, oder dessen Konsole verwendest.

Die Entwickler von Fody empfehlen es, die Konsolen-Variante zu verwenden, ich hatte bisher aber ehrlich gesagt noch nie Probleme mit der GUI-Variante. Gehe oben in Visual Studios Menüleiste auf „Extras“ und wähle „NuGet-Paket-Manager“. Dann wählst Du „Paket-Manager-Konsole“, schon sollte sich ebendiese Konsole öffnen.

Kopiere nun die beiden Befehle und führe Sie einzeln in der Paket-Manager-Konsole aus:

Install-Package Fody
Install-Package PropertyChanged.Fody

Fody konfigurieren

Leider sind wir noch nicht fertig, nachdem wir die notwendigen Pakete installiert haben, noch nicht! Wir müssen die installierten Pakete noch konfigurieren. Fody weiß ansonsten nicht, was es tun soll, bzw. Welche Sub-Pakete (es gibt noch mehr..) verwendet werden sollen.

Wir haben für unseren Bedarf ja das „PropertyChanged.Fody“-Sub-Paket installiert, Dieses konfigurieren wir nun als „wir möchten das gerne verwenden“. Lege dazu im nächsten Schritt eine XML-Datei in Deinem Projektverzeichnis an. Klicke dazu einfach mit einem Rechtsklick auf Deine Projektmappe und wähle „Hinzufügen->Neues Element“. Beachte bitte, dass die neuste Version von Visual Studio eine neue Darstellung – die Kompaktansicht – gewählt hat.

Diese Kompaktansicht kannst Du ganz einfach „ausklappen“, indem Du die jeweilige Option unten links anklickst. Erstelle mit Hilfe des Dialoges nun die XML-Datei und betitle Sie als „FodyWeavers.xml„. In diese Datei gibst Du nun folgenden Text, für unser Beispiel ein:

<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <PropertyChanged />
</Weavers>

Ich hatte hier übrigens ursprünglich nur das „Weavers“-Tag und das Kind „PropertyChanged“ eingefügt. Der Rest wurde später automatisch ergänzt (ehrlich gesagt, keine Ahnung woher, vermutlich durch VS oder Fody selbst). Das sah vorher so aus und reichte wohl auch:

<Weavers>
  <PropertyChanged />
</Weavers>

Unsere finale Klasse

Im letzten Schritt reicht es aus, dass Du einfach nur eine Klasse erstellst, Welche die „INotifyPropertyChanged“-Schnittstelle implementiert – das war’s! Dies kann z. B. durch Vererbung der im anderen Beitrag gezeigten „PropertyChangedBase“-Klasse passieren, oder Du machst es manuell. Ebenso stellt Fody ein Klassen-Attribut zur Vereinfachung bereit.

Beispiel 1 – Vererbung (nach wie vor):

Hier verwenden wir die ganz „normale“ Vererbung, mit der Klasse aus dem anderen Beitrag. Der Vorteil hier ist: Falls wir doch eigene Setter o Ä. schreiben, können wir immer noch auf die Hilfs-Methode „NotifyOfPropertyChange“ zugreifen.

 Public Class SomeThing
    Inherits PropertyChangedBase

    Public Property Company As String

    ' property 2...

    ' property 3...

    ' ...

End Class
public class SomeThing : PropertyChangedBase
{

    public string Company { get; set; }

    // property 2...

    // property 3...

    // ...

}

Beispiel 2 – Mit Attribut von Fody & ohne Vererbung

Hier benötigen wir keine zusätzliche Klasse! Durch das Attribut über der Klasse, weiß Fody, dass hier am Ende die INPC-Schnittstelle automatisch implementiert werden soll – nice!

 Imports PropertyChanged

 <AddINotifyPropertyChangedInterface>
 Public Class SomeThing
    Inherits PropertyChangedBase

    Public Property Company As String

    ' property 2...

    ' property 3...

    ' ...

End Class
using PropertyChanged;

[AddINotifyPropertyChangedInterface]
public class SomeThing
{

    public string Company { get; set; }

    // property 2...

    // property 3...

    // ...

}

„PrivateAssets“-Meldung / Warnung

Durch die Verwendung der vorgestellten Vorgehensweise mit Fody, sparen wir uns (wie Du sicherlich gemerkt haben wirst) eine Menge an Aufwand. Leider kommt es hier und dann noch zu einer kleinen Warnung. Diese Warnung sieht in etwa wie folgt aus:

Warnung FodyPackageReference „Fody: The package reference for PropertyChanged.Fody does not contain PrivateAssets=’All'“

PackageFodyReference - The package reference does not contain PrivateAssets All
PackageFodyReference – The package reference does not contain PrivateAssets All

In meiner aktuellen Installation für diesen Beitrag und dem zugehörigen Video, hatte ich dieses Problem nicht. Vielleicht nimmt das dem ein oder anderen Tester die Angst vor Neuem – es lohnt sich wirklich.

Was bedeutet die „PrivateAssets“-Warnung?

Bevor wir uns an die Problemlösung wagen, sollten wir vielleicht erstmal verstehen, was die Warnung überhaupt bedeutet. Kurzum ist dieses sogenannte „Metadata-Tag“ (ein Schlüsselwort / Stichwort in den Metadaten) dazu da, um Abhängigkeiten zu steuern.

Ich zitiere dazu einfach mal den Punkt aus der offiziellen Dokumentation, wo Du natürlich gerne reinschauen darfst:

Sie verwenden eine Abhängigkeit möglicherweise rein als Entwicklungsumgebung und möchten diese nicht für Projekte verfügbar machen, die Ihr Paket nutzen. In diesem Szenario können Sie dieses Verhalten über die PrivateAssets-Metadaten steuern.

Kurzum heißt das: Wenn wir nicht möchten, dass unsere verwendeten Helferlein (PropertyChanged.Fody, Fody) nach außen sichtbar sind, verwenden wir dieses Metadaten-Tag. Letztendlich brauchen wir Fody nur zur Entwicklung, daher ist es weniger nach außen relevant.

Wie beheben?

Die Warnung dementsprechend zu beheben ist nicht wirklich schwer, es ist letztendlich nur eine Konfigurationssache. Klicke dazu einfach mit einem Rechtsklick auf Dein Projekt und wähle „Projektdatei bearbeiten„. Danach fügst Du einfach das Tag wie im Bild markiert hinzu – schon sollte die Meldung verschwinden!

PrivateAssets All für Fody NuGet Paket festlegen
PrivateAssets All für Fody NuGet Paket festlegen

Downloads

Keine Lust alles abzutippen und manuell ran zu gehen? Verständlich! Lade Dir einfach das passende Beispielprojekt herunter und starte ohne Verzögerung.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert