Wednesday, November 5, 2008

Quick'n'Dirty: Custom Dictionaries für StyleCop

Das erste Quick'n'Dirty dieses Blogs soll sich mit der Definition eines eigenen Wörterbuchs für das Addin "StyleCop" befassen.
Das Tool hat nämlich leider das Problem, dass z.B. Fantasienamen wie "Krytpa" als nicht bekannt gelten (klar, woher auch?) und entsprechend als änderungsbedürftig angezeigt werden.

Dem kann allerdings über ein eigenes Wörterbuch für das Tool leicht Abhilfe geschaffen werden.

Wörterbuch anlegen

Um ein eigenes Wörterbuch anzulegen, muss lediglich eine XML-Datei zum Projekt hinzugefügt werden, welches mit StyleCop analysiert wird.
Diese kann man beliebig benennen, "CustomDictionary.xml" bietet sich allerdings an.

Füllt man diese Datei nun mit folgendem Inhalt, kennt StyleCop plötzlich alle angegebenen Wörter und meldet diese nicht mehr als fehlerhaft. Hier ist natürlich zu beachten, dass nur Wörter ausgeblendet werden, die wirklich nicht fehlerhaft sind, nicht solche, die von StyleCop aus gutem Grund als unbekannt gemeldet werden (auch auf Buchstabendreher achten!).
<?xml version="1.0" encoding="utf-8" ?>
<Dictionary>
<Words>
<Recognized>
<Word>Fantasiewort 1</Word>
<Word>Fantasiewort 2</Word>
</Recognized>
</Words>
</Dictionary>
Hierbei handelt es sich natürlich nicht um den vollständigen Funktionsumfang der eigenen Wörterbücher - deshalb heißt die Rubrik ja auch "Quick'n'Dirty" - sondern nur um einen kleinen (!) Ausschnitt. Im Laufe der Zeit werde ich versuchen, noch mehr solcher nützlichen Methoden aufzuzeigen.

Dictionary einbinden

Zunächst stellte sich bei mir Frustration ein, denn das eigene Wörterbuch wurde vollständig ignoriert!


Ich ärgerte mich bereits, erinnerte mich aber schnell daran, dass solche und ähnliche Probleme oftmals über die Build Action einer Datei (Eigenschaften der Datei aufrufen) gelöst werden können.
Und tatsächlich: Unter Build Action fand sich der Eintrag "Code Analysis Dictionary"! Kaum hatte ich diese Eigenschaft gesetzt, wurden die von mir eingetragenen Wörter als nicht fehlerhaft erkannt und entsprechend auch nicht mehr gemeldet.
Bevor die Eintragungen wirksam werden, ist bei mir ein Rebuild der betroffenen Assembly notwendig!

Spring.NET: Logging einschalten

Da bei der "perfekten Entwicklungsumgebung" natürlich auch Logging-Funktionen nicht fehlen dürfen und bei der Entwicklung von Krypta auch Spring.NET zum Einsatz kommen soll (IOC, etc.), lag es nah, die Spring-Logging-Funktionen zu nutzen.

Leider stellte mich diese Vorgehensweise vor einige Probleme, die ich hier schildern möchte, da ich sicherlich nicht der einzige bin, der damit zu kämpfen hatte.

Zunächst müssen die richtigen Assemblies referenziert werden. Hier zeigte sich das erste Problem, da ich annahm, dass sich diese im Ordner (abhängig von der Version und dem Ort der Installation)
C:\Programme\Spring.Net 1.2.0 RC1\bin\net\2.0\release\
befinden würden.
Entsprechend referenzierte ich die Assemblies Spring.Core, Common.Logging und natürlich log4net.dll aus dem Log4Net-Verzeichnis.

Leider brachte das nicht den gewünschten Erfolg. Visual Studio meldete (im Outputfenster), dass die Konfiguration nicht "richtig" sei und das Logging wollte partout nicht funktionieren.

Letztendlich wurde mir klar, dass die richtigen Assemblies nicht im o.g. Verzeichnis liegen, sondern im Ordner (wieder abhängig von Version und Installationsort natürlich)
C:\Programme\Spring.Net 1.2.0 RC1\lib\Net\2.0\
Aus diesem Verzeichnis müssen die Assemblies wie folgt referenziert werden:

Sind diese Assemblies referenziert, kann die Konfigurationsdatei angelegt werden.

Konfigurationsdatei
Um das Logging zu aktivieren, muss nun noch die Konfigurationsdatei angepasst werden. In diesem Beispiel liegt die Konfiguration für da Logging in der Datei App.config, die über Visual Studio einfach hinzugefügt werden kann.
Die hier gezeigte Konfigurationsdatei wurde hauptsächlich aus den Anleitungen auf www.springframework.net aufgebaut und funktioniert bei mir tadellos, auch wenn ich noch einiges an Arbeit vor mir haben werde, da bin ich mir ziemlich sicher...
Leider ist die hier gezeigte Darstellung etwas unübersichtlich - die vollständige Konfigurationsdatei kann aber am Ende des Artikels unter "Links" heruntergeladen werden.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>

<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />

</configSections>

<spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<description>An example that demonstrates simple IoC features.</description>
</objects>
</spring>

<common>
<logging>
<factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net">
<arg key="configType" value="INLINE" />
</factoryAdapter>
</logging>
</common>


<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>

<!-- Set default logging level to DEBUG -->
<root>
<level value="FATAL" />
<appender-ref ref="ConsoleAppender" />
</root>

<!-- Set logging for Spring to INFO. Logger names in Spring correspond to the namespace -->
<logger name="Spring">
<level value="INFO" />
</logger>
</log4net>

</configuration>


Mit diesen Einstellungen sollte das Logging funktionieren. Ein Beispiel wird im nächsten Abschnitt gezeigt.
Hierbei handelt es sich um einen Logger, der - bei einer Windows Forms - Anwendung im Debug-Fenster (Outputfenster) - in die Konsole schreibt.

Anyone out there? Erste Logmeldung
Ist der obige Teil erst einmal erledigt, wird es Zeit, eine erste Logmeldung auszugeben. Zunächst definieren wir uns einen Logger, den wir - in diesem Beispiel - für die MainForm verwenden wollen:

public partial class Mainform : Form
{
private static readonly ILog _log = LogManager.GetLogger("Spring");
//...
}

Mit diesem Logger ("_log") können nun an beliebiger Stelle Log-Meldungen ausgegeben werden, allerdings erst, nachdem Spring.NET mitgeteilt wurde, dass es sich bitte konfigurieren möchte. Im Konstruktor der MainForm fehlt noch die Zeile
ContextRegistry.GetContext();
Diese bringt Spring.NET dazu, die Konfiguration zu übernehmen.

An beliebiger Stelle kann nun eine Log-Meldung ausgegeben werden:
_log.Info("Hello World");


Fazit

Nach einigen Problemen, die man hätte verhindern können (wahrscheinlich habe ich es einfach überlesen...), funktioniert das Logging einwandfrei.
Zunächst wird für Entwicklungszwecke nur im Debug-Fenster geloggt, aber sobald die Software ausgegeben wird, kann dieses Verhalten über die Konfigurationsdatei leicht auf zahlreiche andere Verfahren umgestellt werden - und das ist die Mühe allemal wert!

Links