C# 预处理器根据环境变量定义符号

ant*_*nta 3 c# attributes preprocessor

我有一些这样的逻辑:

#define MYVAR
...
#if MYVAR
[Attribute1]
#else
[Attribute2]
#endif
Run Code Online (Sandbox Code Playgroud)

我希望能够根据环境变量切换应用于方法的属性,就像MYVAR设置环境变量一样,然后实际定义符号“MYVAR”,反之亦然。

老实说,我不知道这是否可能。如果没有任何想法如何克服这个问题?我当然可以将其添加到方法本身中 - env. 变量检查,但由于正在执行反射,我需要属性。我可以创建自定义MyAttrbute(int mode),但无法在其构造函数中添加逻辑来提取环境。变量,因为它必须是常量表达式。

可能的解决方案:

  • 就像第一条评论所暗示的那样,我可以阅读环境。自定义属性中的变量。仍然会有一些令人讨厌的反思要做。

  • 因为我使用 dotnet 命令在 Linux 上工作,所以我实际上可以将构建命令与 pre-step 命令捆绑在一起,并在文件顶部sed添加一个虚拟占位符,并将其替换为空字符串或基于 env 的完整字符串。变量。这里没有反射,但不是很优雅。{{define_myvar}}.cs

ant*_*nta 5

我找到了一个很好的解决方案。Lasse V. Karlsen 的评论给了我这个想法并在这个领域进行了更多的探索。

C#代码:

        public static void Main(string[] args)
        {
#if MYVAR
            Log.Information("MYVAR defined!");
#else
            Log.Information("MYVAR not defined!");
#endif
        }
Run Code Online (Sandbox Code Playgroud)

项目文件:

<PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <DefineConstants>$(MyVar)</DefineConstants>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

命令:

dotnet build MyProject.csproj -p:MyVar=$MYVAR -c Debug
dotnet run --project=MyProject.csproj -c Debug --no-build
Run Code Online (Sandbox Code Playgroud)

这些命令也可以工作(docker 就绪):

dotnet publish MyProject.csproj -c Release -p:MyVar=$MYVAR
dotnet MyProject.dll
Run Code Online (Sandbox Code Playgroud)

解释:

如果环境。变量$MYVAR设置为MYVAR与 C# 代码中一样,dotnet build将替换 csproj 文件,<DefineConstants>MYVAR</DefineConstants>并且预处理器将评估 #if MYVAR为 true。

如果$MYVAR未设置环境变量(也称为空字符串)或设置为任何其他与不同的值MYVAR,则预处理器会将条件评估为 false。

在我看来,这是一个非常好的调整,适用于不同的场景。谢谢你们的指导,伙计们。干杯。

笔记:

就像问题中所述,我不关心环境变量的值,只关心它是否已定义,即它是否为空字符串。此外,C# 代码只是 PoC,因此使用日志记录比编写属性和折射更容易。