Můj oblíbený systém automatického verzování podle datumu a času není kompatibilní s novými funkcemi .NETu pro snazší vývoj, jako je hot reload a částečná kompilace. To přestane fungovat pokud se při buildu změní verze assembly. Proto jsem musel přijít s jiným způsobem, jak zjistit datum a čas buildu aplikace.
Assembly metadata
Po vydání první verze článku (která popisuje automatické generování resource souboru) jsem byl uživatelem harrison314_sk na Twitteru upozorněn, že existuje jednodušší způsob, jak do assembly vložit datum buildu (a v podstatě jakákoliv jiná metadata).
Stačí do .csproj
souboru vložit element AssemblyMetadata
, kterým můžete přidat do assembly vlastní informace stylem klíč-hodnota. Zde vkládám datum buildu a název počítače, na kterém byl build proveden:
<ItemGroup>
<AssemblyMetadata Include="BuildDate" Value="$([System.DateTime]::UtcNow.ToString('s'))" />
<AssemblyMetadata Include="BuildComputer" Value="$(ComputerName)" />
</ItemGroup>
Popis použité syntaxe a možností najdete v článku MSBuild properties na docs.microsoft.com.
Hodnotu pak můžete načíst přes reflexi. Zde jsou dvě funkce, které načtou a vrátí shora uvedené vlastnosti:
private static DateTime GetAssemblyBuildDate(Assembly? assembly) {
if (assembly == null) return DateTime.MinValue;
var attrs = assembly.GetCustomAttributes<AssemblyMetadataAttribute>();
var dateString = attrs.FirstOrDefault(x => x.Key.Equals("BuildDate"))?.Value;
var parseResult = DateTime.TryParseExact(dateString, "s", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out var dt);
return parseResult ? dt : DateTime.MinValue;
}
private static string? GetAssemblyBuildComputer(Assembly? assembly) {
if (assembly == null) return null;
var attrs = assembly.GetCustomAttributes<AssemblyMetadataAttribute>();
return attrs.FirstOrDefault(x => x.Key.Equals("BuildComputer"))?.Value;
}
Automatické generování do resources
Jako většina ostatních platforem, i .NET zná koncept resources. Tedy ukládání dat jako jsou řetězce, obrázky, ikony a obecná data mimo zdrojový kód tak, aby byla z tohoto kódu snadno dostupná a snadno lokalizovatelná. Tento koncept využívá moje původní metoda pro automatické generování času buildu.
Nejdříve si zobrazte vlastnosti projektu. V sekci Build zvolte Events a do pole Pre-build event zadejte následující příkaz:
powershell -Command "((Get-Date).ToUniversalTime()).ToString(\"s\") | Out-File '$(ProjectDir)Properties\BuildDate.txt'"
Můžete také přímo editovat .csproj
soubor a zadat do elementu <Project>
následující kód:
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="powershell -Command "((Get-Date).ToUniversalTime()).ToString(\"s\") | Out-File '$(ProjectDir)Properties\BuildDate.txt'"" />
</Target>
Poté v sekci Resources klepněte na Create or open assembly resources.
Tím vytvoříte reource ./Properties/Resources.resx
. Můžete ho samozřejmě vytvořit i ručně. Pokud chcete aby byla hodnota viditelná i mimo assembly, nastavte Access Modifier na Public:
Nyní aplikaci zkompilujte. Před kompilací bude vytvořen soubor ./Properties/BuildDate.txt
, který bude obsahovat aktuální datum a čas (UTC) ve formátu yyyy-MM-ddTHH:mm:ss
.
Nyní tento soubor ze Solution Exploreru přetáhněte myší do okna, kde je zobrazen Resources.resx. Tím se vytvoří nový klíč, jehož obsahem bude obsah souboru:
Obsah tohoto souboru se mění s každým buildem, takže když se zeptáte na hodnotu Properties.Resources.BuildDate
, dostanete vždy řetězec obsahující datum a čas, kdy byla aplikace zkompilována.
Pokud používáte Git, přidejte soubor BuildDate.txt
do .gitignore
, ať vám nedělá zmatek v repozitáři.