PostSharp

PostSharp wurde von Gael Fraiteur 2004 ins Leben gerufen. Zunächst handelte es sich um ein Open-Source Projekt, das jedoch mit zunehmenden Featurewünschen zu einem kommerziellen Unternehmen wurde. 2009 wurde das erste kommerzielle PostSharp Release veröffentlicht.
Nun, für was wird PostSharp verwendet? Einfach ausgedrückt zum vereinfachen und aufräumen von Programmcode. Dadurch kann einerseits Entwicklungszeit gesparrt und andererseits auch die Verständlichkeit von Code verbessert werden. PostSharp implementiert einige der am häufigsten verwendeten Pattern in C#. Hierzu zählen:

  • INotifyPropertyChanged: Dieses Interface wird verwendet, um eine GUI oder andere Programmodule über Änderungen eines Objektes zu informieren. Normalerweise muss hier mit Backing Fields gearbeitet werden, was wiederum den Code aufbläht, mit PostSharp kann auf die Backing Fields verzichtet werden.
  • Contracts: Werden zur Validierung eines Fields, einer Property oder eines Parameters verwendet. Dadurch kann unter anderem kontrolliert werden, ob die Eingabe für einen Namen nicht null entspricht.
  • Undo/Redo: Anstatt aufwändiges Abspeichern von Zuständen eines Objektes mithilfe von einer Menge an Code, kann mittels Attribut eine Klasse Recordable gemacht werden.
  • Diagnostics: PostSharp bietet eine Menge von Diangosewerkzeugen an. Hierzu gehört Logging, Metriken, Profiling, etc. Dadurch wird das Finden von verschiedenen Bugs sowie Performanzproblemen um einiges erleichtert.
  • Multi-Threading: Unterstützt das Umsetzen von Multi-Threading Anwendungen, dadurch können viele Codezeilen gesparrt und somit auch die Verständlichkeit verbessert werden.

Es gibt noch viele weiter Einsatzmöglichkeiten wie: Exception Behandlung, Security, etc. die hier nicht weiter im Detail erläutert werden. Im Folgenden werden einige PostSharp Features anhand der Implementierungen eines Taschenrechner-Beispiels aufgezeigt. Bei dem ersten Codeausschnitt handelt es sich um die Umsetzung des INotifyPropertyChanged Interface, es muss nur das Attribut NotifyPropertyChanged gesetzt werden und jede Property wird ohne die manuelle Implementierung des Interfaces und ohne Backing Fields upgedated. Dadurch ist die Lesbarkeit des Codes hervorragend.

[NotifyPropertyChanged]
public class DefaultCalculatorViewModel
{
    #region Commands
    public ICommand PlusCommand { get; private set; }
    public ICommand MinusCommand { get; private set; }
    public ICommand DivideCommand { get; private set; }
    public ICommand MultiplyCommand { get; private set; }
    #endregion
    
    #region Properties
    public double Value1 { get; set; }
    public double Value2 { get; set; }
    public double Result { get; private set; }
    #endregion
    
    #region ctor
    public DefaultCalculatorViewModel()
    {
    	PlusCommand = new DelegateCommand((o) => Result = Value1 + Value2);
    	MinusCommand = new DelegateCommand((o) => Result = Value1 - Value2);
    	DivideCommand = new DelegateCommand((o) => Result = Value1 / Value2);
    	MultiplyCommand = new DelegateCommand((o) => Result = Value1 * Value2);
    }
    #endregion
}

Um eine einfache Undo/Redo Funktionalität zu implementieren wird nur das Attribut Recordable auf der Klasse benötigt. Zusätzlich kann mittels der Angabe eines RecordingScope der Text für ein Undo/Redo gesetzt werden. Von PostSharp werden eigene XAML Controls für die beiden Buttons Undo und Redo angeboten. Die zugehörige dll kann über Nuget heruntergeladen werden.

[NotifyPropertyChanged]
[Recordable]
public class DefaultCalculatorViewModel
{   
    #region Properties
    [RecordingScope("Set Value 1")]
    public double Value1 { get; set; }
    [RecordingScope("Set Value 2")]
    public double Value2 { get; set; }
    [RecordingScope("Updated result")]
    public double Result { get; set; }
    #endregion
    
    ...
}

Das letzte Feature, das aufgezeigt wird, ist das Logging. Hier kann ebenfalls mittels einem Attribut Log das Logging für eine Methode eingeschalten werden. Dadurch wird wieder einiges an Implementierungsarbeit abgenommen. Interessant für das Logging ist das Umschalten des Logging Backends, unter anderem werden Console, Trace, Log4Net, NLog und EnterpriseLibrary unterstützt.

[NotifyPropertyChanged]
[Recordable]
public class DefaultCalculatorViewModel
{
	...
	
    #region ctor
    public DefaultCalculatorViewModel()
    {
        PlusCommand = new DelegateCommand((o) => Plus());
        MinusCommand = new DelegateCommand((o) => Minus());
        DivideCommand = new DelegateCommand((o) => Divide());
        MultiplyCommand = new DelegateCommand((o) => Multiply());
    }
    
    [Log]
    private void Minus()
    {
        Result = Value1 - Value2;
    }
    
    [Log]
    private void Plus()
    {
        Result = Value1 + Value2;
    }
    
    [Log]
    private void Divide()
    {
        Result = Value1 / Value2;
    }
    
    [Log]
    private void Multiply()
    {
        Result = Value1 * Value2;
    }
    #endregion
}

Ausgabe des Loggings, nachdem zwei Zahlen eingegeben und auf den Plus sowie den Minus Button gedrückt wurde.

Debug | Entering: DefaultCalculatorViewModel.Plus(this = {Calculator.ViewModels.DefaultCalculatorViewModel})
Debug | Leaving: DefaultCalculatorViewModel.Plus(this = {Calculator.ViewModels.DefaultCalculatorViewModel})
Debug | Entering: DefaultCalculatorViewModel.Minus(this = {Calculator.ViewModels.DefaultCalculatorViewModel})
Debug | Leaving: DefaultCalculatorViewModel.Minus(this = {Calculator.ViewModels.DefaultCalculatorViewModel})

Das PostSharp Framework ist eine sehr gute Erweiterung für jedes größere C# Projekt. Besonders die beiden Feature INotifyPropertyChanged und Logging sind hervorragend. Bei den anderen Funktionalitäten wie undo/redo sowie Multi-Threading muss sich ein Entwickler einlesen, da diese Konzepte auf einem Parent/Child Relationship Pattern basieren, was meiner Meinung nach den Aufwand Wert ist.

06.03.2017

Calculator Ansicht
Calculator Ansicht