Inversion Of Control(-Container), Service Locator und Dependency Injection

IOC-Container und DI sind zurzeit in vielen Fachzeitschriften diskutiert. Hier der Versuch einer kompakte Übersicht, die IOC, DI, SL und IOC-Container im Zusammenspiel erklärt.

Inversion Of Control

Beschreibt ein Paradigma zum Entwerfen von Frameworks. Ein Unterschied zwischen einem Framework und einer Bibliothek besteht darin, dass in einem Framework Methoden vom Verwender des Framework aufgerufen werden. Dies verändert den Kontrollfluss, bei einer klassischen Bibliothek, ruft der Verwender eine Methode auf, deren Funktionalität wird abgearbeitet und die Methode kehrt zum Aufrufer zurück. Die Steuerung des Kontrollflusses liegt also in der Hand des Verwenders der Bibliothek. Ein gutes Beispiel ist das .NET Framework, der Verwender kann Methoden über Events an Ereignisse binden, dass .NET Framework entscheidet, wann es die Funktionalität des Verwenders aufruft.


Vermeidung von switch-case zur Typen Bestimmung beim Aufruf von generischen Methoden

In der Entwicklung mit .NET hat man öfter folgendes Problem:

Methoden sind generisch implementiert und zu verwendende Objekte sind nur in Form von Referenzen auf Basistypen vorhanden (z.B. System.Array, System.Object). Diese Referenzen können nicht direkt an generische Methode übergeben werden (ergibt einen Compile Fehler).

Häufig liegen daher Typinformationen als String vor (über FullName-Property, aus Konfigurationsdatei, …). Diese Informationen werden anschließend verwendet, um den Typ der Referenz über switch-case aufzulösen.

Zum Beispiel:


UnauthorizedAccessException beim Kopieren einer Datei

Kopieren, verschieben, umbenennen und löschen von Dateien gehören zu häufigen Aufgaben eines Softwareentwicklers. In diesem Beitrag sollen ein paar Dinge aufgezeigt werden die einem beim kopieren von Datein vielleicht nicht bewusst sind. Wie kopiert man jetzt am besten eine Datei? Eine Variante ist die statische Methode der Klasse File:

File.Copy(“C:\\input\\test.bmp“, “C:\\output\\test.bmp“, true);

Damit man sich Überprüfungen wie ob die Datei bereits existiert (File.Exist()) sparen kann, wird die Überladung der Copy-Methode verwendet, welche bestehende Dateien überschreibt. Solange man die Software nur mit administrativen Rechten betreibt, hat man alles richtig gemacht. Muss die Software auch mit Benutzer Rechten arbeiten, kann man hier eine UnauthorizedAccessException bekommen. Dies würde zum Beispiel eintreten wenn eine schreibgeschützte Datei, bereits im Zielverzeichnis existiert und erneut in dieses Verzeichnis kopiert werden soll. Die .Net Implementierung der Copy-Methode fordert Berechtigungen on demand an, das bedeutet erst, wenn besondere Zugriffsrechte benötigt werden, werden diese angefordert. Als Benutzer hat man aber nicht die benötigten Rechte um schreibgeschützte Dateien zu überschreiben. Um diesen speziellen Fall zu lösen, könnte man nach dem kopieren die Attribute der Datei verändern (dafür genügen die Benutzer Rechte):


WPF RichTextBox mit Durchgestrichenden Text

Um bei einer WPF RichTextBox einen Text Fett, Kursiv oder Unterstrichen darzustellen ist nicht viel notwenig. Eigentlich muss man im XAML nur einen (Toggle)Button definieren, der ein Kommando (EditingCommands) an die RichTextBox sendet:

<ToggleButton
  Command="EditingCommands.ToggleItalic"
  CommandTarget="{Binding ElementName=myRichTextBox}"
  Content="Italic"/>
<RichTextBox/>

Genauso einfach verhält es sich einen Text Hochgestellt oder Tiefgestellt darzustellen, mann muss nur zusätzlich noch die Schrift-Familie des Hinter der RichTextBox liegenden Dokumentes verändern:

<ToggleButton
  Command="EditingCommands.ToggleSubscript"
  CommandTarget="{Binding ElementName=myRichTextBox}"
  Content="Subscript"/>
<RichTextBox/>
  <!--on default fontfamily subscript and superscript dont work!!-->
  <FlowDocument FontFamily="Palatino Linotype" FontSize="14"/>
</RichTextBox>

Die Veränderungen an dem Text funktionieren in zwei Modi:


Events über Threadgrenzen

Die meisten Tools/Programme verrichten Ihre Arbeit in Threads um die Oberfläche (UI) nicht zu blockieren. Eine “Kommunikations-Möglichkeit” um die UI beim Eintreten von bestimmten Gegebenheiten zu benachrichtigen sind Events. Ein Event im .Net ruft seine Ziele (InvokationList) aus dem Thread auf, aus dem es “gefeuert” wird. UI Controls, können i.A. nur im Mainthread arbeiten. Einen Zugriff aus einen anderen Thread führt zu einer Exception. Über das Interface ISynchronizedInvoke (implementiert von allen .Net UI Controls):


Tracing/Logging und die Config-Datei

Logging von Informationen ist so gut wie in jedem Programm notwendig. Nicht alle Entwickler können oder wollen ein professionelles Log-Tool wie z.B. log4net oder nlog verwenden. In vielen Fällen reichen auch Debug.WriteLine oder Trace.WriteLine (letztes schreibt auch wenn die Software im Modus „Release“ kompiliert wurde).

Über eine Config-Datei lassen sich u.a. verschiedene TraceListener auswählen:

  1. ConsoleTraceListener
  2. DefaultTraceListener
  3. DelimitedListTraceListener
  4. EventLogTraceListener
  5. EventSchemaTraceListener
  6. TextWriterTraceListener
  7. XmlWriterTraceListener
  8. eigene Implementierungen welche sich von TraceListener ableiten

Damit kann man ohne neu kompilieren des Assemblies einfach den Ausgabeort des Trace-Informationen verändern.


Einiges über IDisposable

Das Standard Interface IDisposable welches  zur “Freigabe” von Ressourcen in .Net dient ist recht Einfach:

public interface IDisposable
{
	void Dispose();
}

Nur dieses Interface zu Implementieren reicht in vielen Fällen nicht aus. Es gibt z.B. einen FxCop Fehler Implement IDisposable correctly, dieser erscheint u.a. bei non-sealed Klassen welche keinen Medthode mit der Signatur protected virtual Dispose(bool) besitzen.  IDisposable zu Implementieren wird nötig wenn man:

  1. unmanged (native) Ressourcen lädt um diese wieder freizugeben
  2. managed Felder besitzt, welche wiederum IDisposable implementieren

Im folgenden Beispiel zeigt eine (nach FxCop komplette Implementierung) einer Basis-Klasse  und einer Kind-Klasse: