Continuous Integration: Трансформация App.config

17 мая 2013 г.

Скачать исходный код

При работе с корпоративными проектами нужно создавать приложения разного рода. Например, проект может содержать несколько веб-сайтов, WCF-сервисы, Silverlight-приложения, Windows-сервисы или консольные утилиты. Все эти приложения нужно будет включить в Continuous Integration, чтобы выпуск версий для тестового сервера и боевого производился в автоматическом режиме. У всех этих приложений есть файлы настроек, которые обычно хранятся в App.config или других XML-подобных файлах. Для разных версий приложений мы должны хранить свои строки подключения к БД, ссылки к сторонним сервисам, SMTP-хостам, задавать разные уровни логирования и т.п.

Мы уже рассмотрели, как работать с Web.config, как писать для него трансформацию, что такое трансформация и как она встраивается в процесс сборки проекта. Продолжим эту тему рассмотрением работы с App.config.

Создание App.config для каждой конфигурации

Для примера я создал два проекта: Консольное приложение и WPF приложение. В обоих проектах используются App.config и изначально они выглядят так:

В солюшене по-умолчанию есть две конфигурации и я сразу добавил еще одну (как добавлять конфигурацию мы рассматривали в статье Continuous Integration: Создание собственной конфигурации):

Для каждой конфигурации сборки мы создадим файл трансформации. Первое, что надо сделать - создать 3 файла: App.Debug.config, App.UAT.config, App.Release.config.

Теперь сделаем, чтобы эти файлы конфиугаций красиво отображались в дереве солюшена. Для этого откроем файл проекта в текстом редакторе и добавим в секцию с App.cofing XML-код:

ConsoleApp.csproj:

<ItemGroup>
  <None Include="App.config" />
  <None Include="App.Debug.config">
    <DependentUpon>App.config</DependentUpon>
  </None>
  <None Include="App.UAT.config">
    <DependentUpon>App.config</DependentUpon>
  </None>
  <None Include="App.Release.config">
    <DependentUpon>App.config</DependentUpon>
  </None>
</ItemGroup>

После обновления файла проекта Visual Studio отобразит наши файлы:

Описываем трансформацию в App.config

Мы создали файл трансформации для каждой конфигурации сборки. Для примера я добавил трансформации ключа в секции appSettings.

App.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="SmtpHost" value="debug-smtphost"/>
  </appSettings>
</configuration>

App.Debug.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add xdt:Transform="Replace" xdt:Locator="Match(key)" key="SmtpHost" value="debug-smtphost"/>
  </appSettings>
</configuration>

App.Release.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add xdt:Transform="Replace" xdt:Locator="Match(key)" key="SmtpHost" value="release-smtphost"/>
  </appSettings>
</configuration>

App.UAT.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add xdt:Transform="Replace" xdt:Locator="Match(key)" key="SmtpHost" value="uat-smtphost"/>
  </appSettings>
</configuration>

Обратите внимание на указание пространства имен: xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"

В примере мы используем Replace для замены всего нода в XML, но кроме полной замены TransformXml поддержиет и другие трасформации. Более подробно о них на MSDN.

Включаем трансформацию App.config

Для того, чтобы описанные трансформации начали применяться, нужно включить их в процесс сборки проекта. В файле проекта добавляем:

ConsoleApp.csproj:

<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.dll"/>
<Target Name="AfterBuild">
  <TransformXml Source="App.config" Transform="App.$(Configuration).config" Destination="App.config" StackTrace="true" />
</Target>

Мы использовали элемент UsingTask для подключения задач из сборки Microsoft.Web.Publishing.Tasks.dll. Вы можете скопировать эту сборку и связанные с ней к себе в проект, чтобы указать для подключения локальный путь, а саму сборку добавить в source control.

Переключим конфигурацию сборки в Release и запустим Build проекта. Мы видим, что в файл App.config были подставлены данные из App.Release.config:

Итоги

Включение трансформации для App.config осуществляется в 2 шага: добавить трансформации, включить трансформацию во время сборки проекта. Часть операций приходится делать вручную.

Таким же образом можно включить трансформации для любых XML-файлов.


Статья из серии Continuous Integration: Работа с Config-файлами:

  1. Continuous Integration: Трансформация Web.config
  2. Continuous Integration: Процесс сборки проекта и трансформации Config-файлов
  3. Continuous Integration: Создание собственной конфигурации
  4. Continuous Integration: Трансформация App.config
  5. Continuous Integration: Рефакторинг файлов конфигурации

Моя книга «Антихрупкость в IT»

Как достигать результатов в IT-проектах в условиях неопределённости. Подробнее...