Reputation: 123
In our C# code we have a static class with a Boolean variable IS_FEATURE_X_ENABLED
and we want to be able to set this variable during the compile time, means when we call MSBuild.exe the value will be included as an argument. For example:
MSBuild.exe FeatureFlexibleApp.sln -p:IsFeatureXEnabled=true
The reason for this is that we want to be able to build binaries with a specific configuration, but before the compilation this value is not known. If a customer wants this feature, they can select that on our web page and the binaries will be built and packaged on a Jenkins server, then a download link will be sent to the user (either per email or it will be shown on the webpage if they wait for the compilation to finish). In this case only one variable is used, but in reality this number does not have to have a limit (so pre-building all possible combinations is not a feasible option).
Upvotes: 3
Views: 770
Reputation: 42245
You've got 2 options.
The first is to use this MSBuild property to control whether a particular preprocessor symbol is defined, and then use #if
in your C# code:
<PropertyGroup>
<DefineConstants Condition="'$(IsFeatureXEnabled)' == 'true'">$(DefineConstants);IS_FEATURE_X_ENABLED</DefineConstants>
</PropertyGroup>
then:
#if IS_FEATURE_X_ENABLED
// Code compiled only if feature X is enabled
#endif
But, if you're going down this route, it's easier to scrap the boilerplate in the csproj, and just set DefineConstants directly from the command line:
MSBuild.exe FeatureFlexibleApp.sln -p:DefineConstants=IS_FEATURE_X_ENABLED
Another is to use the value of the MSBuild property to write an assembly-level attribute, and then read this attribute with code at runtime.
The only thing which changes between different builds of your assemblies is the values of these assembly-level attributes: everything else is determined at runtime, which may or may not be what you want. However, it does mean you can pass any old string into your code, rather than just binary enabled / not enabled.
<ItemGroup>
<AssemblyAttribute Include="Namespace.Of.Your.ConfigurationAttribute">
<IsFeatureXEnabled>$(IsFeatureXEnabled)</IsFeatureXEnabled>
</AssemblyAttribute>
</ItemGroup>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
internal class ConfigurationAttribute : Attribute
{
public string IsFeatureXEnabled { get; set; }
}
...
bool isFeatureXEnabled = typeof(...).Assembly
.GetCustomAttribute<ConfigurationAttribute>().IsFeatureXEnabled == "true"
Upvotes: 3