15.02.2013 Aufrufe

b2aat6n

b2aat6n

b2aat6n

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

thode mehrere Parameter von einfachen<br />

Typen erwarten, müsste jemand, der den<br />

Code liest, daraus gedanklich die Dienstbeschreibung<br />

erst wieder zusammensetzen.<br />

Das Datenmodell für die Dienstbeschreibung<br />

sieht aus wie in Listing 5.<br />

Die Kontrakte für die Funktionseinheiten<br />

sind in EBC-Manier erstellt. Das bedeutet,<br />

dass sie über sogenannte Inputund<br />

Outputpins verfügen. Inputpins werden<br />

in Form von Methoden modelliert,<br />

Outputpins sind Events. Zu weiteren Details<br />

über EBCs lesen Sie am besten die<br />

Artikelserie von Ralf Westphal, zu finden<br />

unter [1] [2] [3]. Der Kontrakt für das Auswerten<br />

der Argumente sieht aus wie in Listing<br />

6. Auf dem Inputpin In_Process der<br />

Funktionseinheit werden die Kommando-<br />

Listing 4<br />

Eine statische Methode<br />

„Run” verwenden.<br />

EasyService.Run(<br />

args,<br />

"myService",<br />

"Mein Service",<br />

"Ein Service, der nichts tut.",<br />

() => Trace.WriteLine<br />

("OnStart aufgerufen"),<br />

() => Trace.WriteLine<br />

("OnStop aufgerufen")<br />

);<br />

Listing 5<br />

Datenmodell für die Dienstbeschreibung.<br />

public class ServiceBeschreibung<br />

{<br />

public string Name { get; set; }<br />

public string DisplayName { get; set; }<br />

public string Description { get; set; }<br />

}<br />

Listing 6<br />

Argumente auswerten.<br />

public interface IArgumenteAuswerten<br />

{<br />

void In_Process(params string[] args);<br />

event Action Out_Install;<br />

event Action Out_Uninstall;<br />

event Action Out_RunAsService;<br />

}<br />

[Abb. 2] Verfeinerung<br />

des Entwurfs.<br />

zeilenparameter in Form eines string-Arrays<br />

übergeben. Je nachdem, welcher Parameter<br />

übergeben wurde, wird daraufhin<br />

der korrespondierende Outputpin ausgelöst.<br />

Die beiden Kontrakte für die Installation<br />

und Deinstallation sind noch einfacher, da<br />

sie nicht über Outputpins verfügen, siehe<br />

Listing 7.<br />

Und zu guter Letzt ist da noch der Kontrakt<br />

für die Ausführung des Service, siehe<br />

Listing 8.<br />

Damit haben Sie nun alle Kontrakte zusammen<br />

und können mit der Implementierung<br />

beginnen. Wie schon angedeutet,<br />

sind automatisierte Tests an den Stellen<br />

schwierig, an denen die Windows-Infrastruktur<br />

relevant ist. Dies betrifft das Installieren<br />

und Deinstallieren des Dienstes. Ferner<br />

sollte der Kontrakt IServiceAusführen<br />

mit der abstrakten Klasse ServiceBase aus<br />

dem .NET Framework kombiniert werden.<br />

Diese stellt die erforderliche Infrastruktur<br />

für die Dienstausführung zur Verfügung.<br />

Damit die Dienste nicht von ServiceBase<br />

ableiten müssen und tatsächlich keine Abhängigkeiten<br />

zur Windows-Infrastruktur<br />

haben, verwende ich einen Dienstproxy.<br />

Diese Klasse leitet von ServiceBase ab und<br />

bietet zwei Events, die beim Starten bzw.<br />

Stoppen des Dienstes ausgeführt werden.<br />

Dadurch kann ein Lambda-Ausdruck verwendet<br />

werden, und der Dienst ist infra-<br />

Listing 7<br />

Installation und Deinstallation.<br />

public interface IServiceInstallieren<br />

{<br />

void In_Installieren(ServiceBeschreibung beschreibung);<br />

}<br />

public interface IServiceDeinstallieren<br />

{<br />

void In_Deinstallieren(ServiceBeschreibung beschreibung);<br />

}<br />

LÖSUNG<br />

strukturunabhängig. Der Dienstproxy sieht<br />

aus, wie in Listing 9 gezeigt wird.<br />

Diese Klasse ist so simpel, dass ich auf<br />

Tests verzichtet habe. Sie zu ergänzen würde<br />

im Übrigen auch erfordern, die protected<br />

Methoden OnStart und OnStop im<br />

Test aufzurufen. Aufgrund der Vererbung<br />

kann die Sichtbarkeit nicht zu internal geändert<br />

werden. Aufwand und Nutzen stünden<br />

daher in einem sehr ungünstigen Verhältnis.<br />

Da das gesamte Projekt ohnehin<br />

einen Integrationstest erfordert, wird der<br />

ServiceProxy dort mitgetestet.<br />

Sehr gut automatisiert zu testen ist die<br />

Implementierung der Argumentauswertung.<br />

Ich habe die Klasse ArgumenteAuswerten<br />

testgetrieben entwickelt. Listing 10<br />

zeigt zwei der Tests als Beispiele.<br />

Der erste Test prüft, ob beim Aufruf ohne<br />

Parameter der Outputpin Out_RunAs-<br />

Service ausgelöst wird. Dies ist wichtig, da<br />

Windows den Dienst so startet. Der zweite<br />

Test prüft, ob bei Aufruf mit /install der<br />

Event Out_Install ausgelöst wird.<br />

Die zugehörige Implementierung ist einfach<br />

gehalten. Zunächst wird geprüft, ob<br />

kein Argument übergeben wurde. In dem<br />

Fall wird der Event Out_RunAsService ausgeführt.<br />

Andernfalls wird über ein switch-<br />

Statement in die jeweiligen Events verzweigt.<br />

Diese Form der Argumentauswertung<br />

ist zwar zu einfach, um damit etwa zusätzliche<br />

Parameter zu den Optionen parsen<br />

www.dotnetpro.de dotnetpro.dojos.2011 47

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!