Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
App.config Generator
mosspower
myCSharp.de - Member

Avatar #avatar-2662.jpg


Dabei seit:
Beiträge: 456
Herkunft: Bamberg

Themenstarter:

App.config Generator

beantworten | zitieren | melden

Background:
Ihr kennt ja sicherlich auch, wie nervig das ist, wenn man Configfiles pflegen muss für Testumgebung und Liveumgebung. Da wird hin- und herkopiert, teilweise zwei Files erstellt, ein- und auskommentiert usw. Auch übel ist, wenn für einen Kunden mehrere Projekte (Consoleanwendung, Service, Admin-GUI ect.) erstellt werden und diese zu 80 Prozent identische Constanten (Datenbank, Resourcen, Pfade ect.) haben. Dann wird wieder kopiert, neue Files erstellt, und wenn es mal größere Änderrungen (Datenbank, Server, Pfade ect.) gibt, dann geht nix mehr (oder man ist einen Tag drüber das Gedöns glattzustellen). Leidig ist das Thema auch, wenn viele Mitarbeiter am gleichen Projekt arbeiten und es sehr viele Keys im Configfile gibt, Stichwort Mergekonflikte, bzw. "Zerschießen" von Eintragungen, die ein Kollege bereits eingechecked hat, weil man die "überbuttert" hat.

Lösung:
Ich habe einen Generator geschrieben, der genau dies in Zukunft verhindert. Man kann "normale" Values nehmen, die gelten für Test- und Produktionsumgebung, oder aber, je nach Bedarf, die Prefixe test. oder prod. dem Attributnamen voranstellen. Aufgrund des Attribute-Flags production, im Element configuration, wird dann der jeweils benötigte Wert durch den Generator eingesetzt. Auch können abhängig von der ausgeführten Assembly Einträge vorgenommen werden, (appSettings > sections), so dass nur die relevanten Sectionen generiert werden. Bei der Generierung wird ein Schema verwendet, das ist eincompiliert, bzw. eine embedded Resource. Eins vorweg. Ich habe das auch mit einer Web.config getestet, funktioniert wunderbar, alle Teile, die nicht im Schemafile definiert sind, z.B. (system.web oder runtime) müssen dann in das Element custom eingefügt werden. Nichtsdestotrotz werden auch hier die jeweiligen Values ersetzt. Bei Benutzung von Domaincontrollern müssen manuelle Anpassungen durchgeführt werden. Was der Generator gegenwärtig macht, und mir reicht das erst mal völlig, ist, dass immer im Ausführungsverzeichnis der Anwendung, z.B. Name der Anwendung ist GenerationTest, die Datei GenerationTest.exe.config erstellt wird. Bei Webanwendungen wird im Projektrootverzeichnis immer die Web.config erstellt. Desweiteren werden auch Konstanten unterstützt, diese sind sehr hilfreich, bei mehereren Pfadangaben auf z.B. dem gleichen Server, für diesen braucht dann nur einmal eine globale Variable erstellt werden.

So, fangen wir mal mit einem Screenshot und einem kleinen Beispiel an ...

Schlagwörter: Configuration, Config. App.config
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von mosspower am .
Attachments
private Nachricht | Beiträge des Benutzers
mosspower
myCSharp.de - Member

Avatar #avatar-2662.jpg


Dabei seit:
Beiträge: 456
Herkunft: Bamberg

Themenstarter:

beantworten | zitieren | melden

Der Screenshot zeigt ein einfaches Template-File. Das Root-Element lautet configuration, wie auch im generierten Config-File, hier habe ich aber zusätzlich noch das Attribut production eingebaut. Dies ist der Schalter für Produktions- oder Testumgebung.

Danach habe ich das constants Element eingebaut. Hier können globale Variablen deklariert werden - man kann sich aussuchen, ob diese globalen Variablen für alle Umgebungen gleich (Attribute value) oder unterschiedlich (Attribute test.value und prod.value) vorhanden sind. Eingebunden werden die Variablen dann einfach mit der Schreibweise ${key} (ja, ja, der sogenannte Ant-Style - man kommt nie ganz weg von Java). Der Generator ersetzt dann alle Vorkommnisse im Quellcode (die Variablen dürfen auch öfters in einem value-Attribut vorkommen, siehe key modul.a.q.file.

Danach kommen die bereits bekannten configSections- und connectionStrings-Abschnitte ... sollten klar sein denke ich

Dann der ebenfalls bekannte Abschintt appSettings. Hier habe ich ein Zusatzelement section eingebaut, so dass hier nach Modulen, Aufgaben, Einheiten oder Projekte gekapselt werden kann. Hier kommen sich dann verschiedene Entwickler nicht in die Quere, oder aber man benutzt ein Configfile für meherere Projekte. Aufpassen muss man hier, dass man Unique-Keys (wie im normalen App.config File ja auch) verwendet (sollten halt sprechend sein - ich schreibe immer lange Keynamen mit Punkt getrennt, wie in den guten alten Java-Propertyfiles). Im Attribut name kann man dann nähere Angaben machen, wie z.B. ein Modul beschreiben. Will man eine Section nur für ein oder bestimmte Projekte generieren lassen, dann benutzt man das optionale Attribut include. Hier können mit Pipes getrennt, Projektnamen angegeben werden. Nur für diese wird dann das section Element aufgelöst und generiert. Standardmäßig werden alle section Elemente generiert, wenn nicht explizit include-Element angegeben ist. Der Generator entfernt dann alle section-Elemente und fügt alle add-Elemente an das appSettings-Element.

Zum Schluß kann man dann noch das custom-Element verwenden für eigene Sections. Hier werden dann auch die values dementsprechend ersetzt.

Der Output, also das generierte Configfile, sieht dann so aus, bei production="true" ...
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von mosspower am .
Attachments
private Nachricht | Beiträge des Benutzers
mosspower
myCSharp.de - Member

Avatar #avatar-2662.jpg


Dabei seit:
Beiträge: 456
Herkunft: Bamberg

Themenstarter:

beantworten | zitieren | melden

Der Outputf für die Testumgebung sieht dann so aus, bei production="false" ...
Attachments
private Nachricht | Beiträge des Benutzers
mosspower
myCSharp.de - Member

Avatar #avatar-2662.jpg


Dabei seit:
Beiträge: 456
Herkunft: Bamberg

Themenstarter:

beantworten | zitieren | melden

In Zukunft braucht man also kein App.config (oder Web.config) File mehr ... ich löse das dann einfach mit einem Template-File, dass ich in der Umgebung manipuliere, siehe Screenshot ...
Attachments
private Nachricht | Beiträge des Benutzers
mosspower
myCSharp.de - Member

Avatar #avatar-2662.jpg


Dabei seit:
Beiträge: 456
Herkunft: Bamberg

Themenstarter:

beantworten | zitieren | melden

So, jetzt wird der ein oder andere einwenden, dass man das immer zweimal compilieren muss, da ja das Auslesen des Configfiles vor dem Ausführen des Quellcodes gecached wird ... auch dafür eine Lösung, ich habe einen eigenen Task geschrieben, diesen bindet ihr dann folgendermaßen in die jeweilige Projektdatei ein:
<UsingTask TaskName="Generator.AppConfig.AppConfigGeneratorTask" AssemblyFile="lib\Generator.AppConfig.dll" />

  <Target Name="AppConfigGeneratorTarget">
    <AppConfigGeneratorTask QTemplateFile="App.config.template" QProjectHome="$(MSBuildProjectDirectory)" Release="$(Configuration)" Web="false" />
  </Target>

  <Target Name="BeforeBuild" DependsOnTargets="AppConfigGeneratorTarget" />
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von mosspower am .
private Nachricht | Beiträge des Benutzers
mosspower
myCSharp.de - Member

Avatar #avatar-2662.jpg


Dabei seit:
Beiträge: 456
Herkunft: Bamberg

Themenstarter:

beantworten | zitieren | melden

Jetzt könnt ihr wie gewohnt arbeiten, denn jetzt wird immer vor einem Build der Task zum generieren des Configfiles ausgeführt.

Anbei noch der Quellcode (alles mit 3.5 compiliert, sollte aber auch mit 2.0 laufen, hier muss dann aber BuildFramework von 2.0 eingebunden werden) - viel Spass dabei.
Attachments
private Nachricht | Beiträge des Benutzers