В мире C++ я решал подобные штуки очень просто с использованием define и опций компилятора. Но в .Net define не имеют значений кроме true/false, т.е. они либо определены либо нет. Насколько я понимаю, их цель это простейшая условная компиляция.
Кому интересно решение добро пожаловать под кат.
Первая мысль, которая меня посетила: перед билдом сгенерить файлик с константами по шаблону, но хотелось бы обойтись без привлечения тяжелой артиллерии шаблонизаторов.
После некоторых поисков я обнаружил интересный факт. В .Net есть механизм атрибутов. Эти атрибуты можно цеплять к классам, методам, полям и всяким разным сущностям. Оказалось что его можно цепануть ко всей сборке целиком.
В файлах проектов (.csproj) есть возможность выставлять значения этим атрибутам при сборке. А в MSBuild можно передать параметры извне через механизм пропертей. Вроде все сходится, надо пробовать.
Создаем новое консольное приложение:
% mkdir Example && cd Example % dotnet new console
Создаем файл ExampleAttribute.cs с определением нашего атрибута.
using System; namespace Example { [AttributeUsage(AttributeTargets.Assembly)] //Указываем что атрибут цепляется к сборке public class ExampleAttribute : Attribute { public string Value { get; set; } public ExampleAttribute(string value) { Value = value; } } }
Далее файл Example.csproj приводим к следующему виду. Я добавил комментарии, дабы суть изменений была ясна.
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> <RootNamespace>Example</RootNamespace> <ExampleValue>default</ExampleValue> <!-- Добавляем нашу кастомную пропертю с дефолтным значением --> </PropertyGroup> <!-- Добавляем этот блок для опледеления значения атрибута при сборке --> <ItemGroup> <AssemblyAttribute Include="Example.ExampleAttribute"> <!-- Указываем класс атрибута --> <_Parameter1>$(ExampleValue)</_Parameter1> <!-- Выставляем значения для вызова конструктора --> </AssemblyAttribute> </ItemGroup> </Project>
Ну и собственно получение значения на рантайме в Project.cs
using System; using System.Reflection; namespace Example { class Program { static void Main(string[] args) { var assembly = Assembly.GetExecutingAssembly(); var attr = (ExampleAttribute) assembly.GetCustomAttribute(typeof(ExampleAttribute)); Console.WriteLine($"Assembly attribute value = '{attr.Value}'"); } } }
Итак соберем и запустим, дабы посмотреть что у нас получилось.
% dotnet build . % dotnet run --no-build . Assembly attribute value = 'default'
А теперь с параметром:
% dotnet build . /p:ExampleValue="NOT DEFAULT" % dotnet run --no-build . Assembly attribute value = 'NOT DEFAULT'
Вуаля, цель достигнута. Пользуйтесь на здоровье.
ссылка на оригинал статьи https://habr.com/ru/post/492216/
Добавить комментарий