Patterns und Practices für die Softwareentwicklung in .NET: die Enterprise Library. Teil 1: Unity

“Für viele Vorgänge, welche man tagtäglich in der .NET Entwicklung benötigt gibt es bereits viele hilfreiche Libraries. In dieser Serie werden best practices vom Patterns&Practices Team vorgestellt.”

Unity ist eine der Bestandteile der Enterprise Library, welche Patterns und Practices für die .NET Entwicklung beinhaltet. Unity verwendet man, um Dependency Injection zu ermöglichen. Dependency Injection ist eine Implementierung des IoC Patterns (Inversion of Control – zu deutsch in etwa “Umkehr der Kontrolle). Das bedeutet das die Erzeugung und das Verknüpfen von Objekten ausgelagert wird. Der Vorteil hierbei ist die verbesserte Testbarkeit, jedoch entsteht auch der Nachteil das die Projekte eventuell unüberschaubar werden. Unity regelt nun die eben beschriebene Verwaltung. Oft wird Unity auch ohne andere Komponenten der Enterprise Library eingesetzt, da Dependency Injection eine zentrale Komponente in der Softwareentwicklung ist. Unity verwendet man dann, wenn man viele Abhängigkeiten zwischen Objekte hat, die Objekte sehr komplex sind und man daher abstraktion benötigt, wenn man Abhängigkeiten zur Laufzeit ändern will oder dergleichen.

Was braucht man um mit Unity loszulegen?

Als erstes benötigt man die Enterprise Library. Zum Zeitpunkt der Erstellung dieses Beitrages war die Version 5.0 aktuell. Diese kann man über https://unity.codeplex.com/ erhalten. Danach muss man Unity nur noch in das Projekt einfügen.

Dann kann man an sich bereits mit der Erstellung von Unity Containern beginnen. Diese Container kann man entweder per Code erstellen oder über die App.config (Client Anwendungen) oder der Web.config (Webanwendungen). In diesem Beitrag wollen wir die Dependencies nur per XML konfigurieren. Hierfür muss, sollte die Konfiguration nicht vorhanden sein, eine neue Anwendungskonfiguration eingefügt werden.

imagePLWMH5XW

Nun kann man mit der XML-Konfiguration beginnen. Wir fügen die Inhalte in den Knoten “configuration” ein. Hier müssen wir zum Einem Unity konfigurieren (configSections) und zum anderen Unity selbst im Knoten “unity”.

Der Unterknoten “typeAliases” von “unity” enthält hierbei die Interfaces und Implementierungen die verwendet werden. Ferner wird ein Container benötigt, welche die Auflösung der Services erstellt. Der Container wird in der Sektion “containers” definiert. Ein Typ wird mit dem Typen und der jeweiligen Implementierung (mapTo) aufgelöst. Services, die man hier verwendet müssen unter “typeAliases” angegeben werden. Will man ein Service als Singleton registrieren so kann man dies im Knoten “lifetime” erledigen. Ein komplettes Beispiel ist in der folgende XML Datei dargestellt.

 <?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
                                Microsoft.Practices.Unity.Configuration, Version=2.0.414.0,
                                Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  </configSections>

  <unity>
    <typeAliases>
      <!-- Interfaces -->
      <typeAlias alias="ILanguageService" type="Some.Application.ILanguageService, Some.Services"/>
      <typeAlias alias="IApplicationPageService" type="Some.Application.IApplicationPageService, Some.Services"/>
      <typeAlias alias="IApplicationSettingsService" type="Some.Application.IApplicationSettingsService, Some.Services"/>
      
      <!-- Implementations -->
      <typeAlias alias="LanguageService" type="Some.Application.LanguageService, Some.Services"/>
      <typeAlias alias="ApplicationPageService" type="Some.Application.ApplicationPageService, Some.Services"/>
      <typeAlias alias="ApplicationSettingsService" type="Some.Application.ApplicationSettingsService, Some.Services"/>
      
    </typeAliases>
    <containers>
      <container name="basicServices">
        <types>

          <type type="ILanguageService" mapTo="LanguageService">
            <lifetime type="singleton" />
          </type>

          <type type="IApplicationPageService" mapTo="ApplicationPageService">
          </type>

          <type type="IApplicationSettingsService" mapTo="ApplicationSettingsService">
          </type>
          
        </types>
      </container>
    </containers>
  </unity>

</configuration>

Schlussendlich muss Unity auch in der Anwendung noch konfiguriert werden. Hierfür erstellt man sich den UnityContainer und ließt die Konfiguration mit dem ConfigurationManager aus. Dies sieht dann folgendermaßen aus:

 UnityContainer myContainer = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(myContainer, "basicServices");

Im nächsten Teil werde ich den ServiceLocator einbauen, damit Unity interessanter zu verwenden ist.