воскресенье, 24 июня 2012 г.

Генерация Assembly Version при помощи T4 шаблонов

[Generation of Assembly Version using the T4 templates]

Assembly Version используется .NET фреймворком во время построения и во время исполнения приложения для определения загружаемой сборки. Другими словами, Assembly Version является важной частью имени сборки, ее однозначно определяющей.

Assembly File Version является номером версии файла (отображается в Windows Explorer) и НЕ ИСПОЛЬЗУЕТСЯ .NET-ран-таймом для локализации сборки.

Эти версии указываются в атрибутах сборки и как правило находятся в файле AssemblyInfo.cs:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]


Если сборки создаются очень часто, ручное изменение значений указанных атрибутов становится накладным. Для автоматического увеличения номера построения (Build Number) и ревизии (Revision) можно использовать символ звездочки (*):
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.*")]


Компилятор сгенерирует номера самостоятельно, и этого в большинстве случаев будет достаточно. Но выдаваемые номера трудно поддаются интерпретации , и если хочется наделить числа большим смыслом, например, привязать к дате/времени, придется делать это при помощи сторонних средств. Для этих целей есть множество утилит и надстроек к Visual Studio в виде AddIn-ов, я же воспользуюсь встроенными средствами Visual Studio - генерацей кода по текстовым шаблонам: Text Template Transformation Toolkit, или коротко T4. При помощи этого инструмента можно генерировать заветные строки самостоятельно, наделив нумерацию необходимой логикой. У меня в примере нумерация привязана к году, месяцу, числу, и часу, когда создается сборка. Добавьте новый файл шаблона в проект, и назовите его, например, “AssemblyVersion.tt”:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
// Assembly Version
// Generated at <#= DateTime.Now #>
//
// [major version].[minor version].[build number].[revision number]
// build number = yy MM = Year Month (e.g.: 1102 = 2011 February)
// revision number = ddHH = Day Hour (e.g.: 1411 = 14 "February" at 11 )
//
// to generate for every build in BuildEvents:
// "%CommonProgramFiles%\Microsoft Shared\TextTemplating\10.0\TextTransform.exe" "$(ProjectDir)AssemblyVersion.tt" -out "$(ProjectDir)AssemblyVersion.cs"

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: AssemblyVersion("1.0.<#= DateTime.Now.ToString("yyMM") #>.<#= DateTime.Now.ToString("ddHH") #>")]
[assembly: AssemblyFileVersion("1.0.<#= DateTime.Now.ToString("yyMM") #>.<#= DateTime.Now.ToString("ddHH") #>")]


Генерация кода по файлам шаблонов (*.tt) происходит автоматически при сохранении изменений в шаблоне или при явном вызове соответствующей команды (например из контекстного меню). Также можно попросить Visual Studio обработать все шалоны проекта. Но нам нужно добиться генерации при каждом построении (build) проекта. Для этого можно воспользоваться этим (http://msdn.microsoft.com/ru-ru/library/ee847423.aspx) руководством от MS "Создание кода в процессе построения".  Я же вызываю генератор шаблонов из командной строки в Prebuild-событии:

"%CommonProgramFiles%\Microsoft Shared\TextTemplating\10.0\TextTransform.exe" "$(ProjectDir)AssemblyVersion.tt" -out "$(ProjectDir)AssemblyVersion.cs"


Не забудьте удалить или закомментировать ненужные уже строки в файле AssemblyInfo.cs!


Замечания:
- Не уверен, но кажется, что генерация по шаблонам T4 не поддерживаются в Visual Studio Express - версии.
- Вам не обойтись от изменения версии файла (AssemblyFileVersion) если вы в проекте установки (Setup Project) используете параметр "RemovePreviousVersion=true". Файлы обновляются, только если имеют большую версию, чем уже установленые.
- Для проекта типа Class Library (Visual Basic) в Visual Studio 2010 автоматическая генерация версии при помощи знака (*) не срабатывает. Это известная проблема описана здесь (https://connect.microsoft.com/VisualStudio/feedback/details/588047), поэтому для автоматической генерации вам, наверное, придется использовать "внешние" средства, такие как T4.
- Если необходимо, чтобы все сборки проекта имели одинаковый номер версии, можно воспользоваться следующим способом:
    -- Удалите определяющие версию атрибуты во всех проектах (файлы AssemblyInfo).
    -- В одном из проектов создайте файл с атрибутами версии (AssemblyVersion, AssemblyFileVersion). Можно воспользоваться описанной в статье кодо-генерацией.
    -- Добавьте этот файл к каждому из проектов, но КАК ССЫЛКУ (as link).

------------------------------------------

Ресурсы:
How to use Assembly Version and Assembly File Version
http://support.microsoft.com/kb/556041/en-us

Создание кода и текстовые шаблоны T4
http://msdn.microsoft.com/ru-ru/library/bb126445

Official T4 team blog - официальный блог команды разработчиков t4
http://blogs.msdn.com/b/t4/
И их официальный блог примеров
http://t4talk.codeplex.com/

Комментариев нет: