基于环境变量的C#预处理器定义符号

3

我有一些类似这样的逻辑:

#define MYVAR
...
#if MYVAR
[Attribute1]
#else
[Attribute2]
#endif

我想能够根据环境变量切换应用于方法的属性,就像如果设置了环境变量MYVAR,则实际上定义符号'MYVAR',反之亦然。

说实话,我不知道是否可能。如果不行,有什么办法可以克服吗?当然我可以在方法本身中添加这个 - env. 变量检查,但是由于要执行反射,所以我需要这些属性。 我可以创建自定义的MyAttrbute(int mode),但无法在其构造函数中添加逻辑来提取env.变量,因为它必须是常量表达式。

可能的解决方案:

  • 像第一个评论所建议的那样,在自定义属性中读取env.变量。仍然需要进行一些讨厌的反射工作。

  • 因为我正在使用Linux with dotnet commands工作,我实际上可以将我的构建命令与预步骤sed命令捆绑在一起,并在.cs文件的顶部添加一个虚假占位符{{define_myvar}},并根据env.变量用空字符串或完整字符串替换它。这里没有反射,但不太优雅。


你可以在属性内读取环境变量。 - Guru Stron
好的,这是一个选项,可以向自定义属性添加公共属性并进行一些反射操作。但问题仍然存在,是否有更简单的方法。 - antanta
3
您可以通过构建脚本将环境变量传递给编译器,但是您 C# 代码中的标识符不会为您查找环境变量。在属性中使用代码也是错误的,因为它将在运行时被评估,而 #if xxx 将在编译时被评估。 - Lasse V. Karlsen
2
说实话,我不太明白反射等技术如何涉及其中。你能否更详细地解释一下你的使用情况,因为目前看来似乎存在更深层次的问题。 - Guru Stron
你可以使用 T4 模板来定义全局符号。 - Charlieface
1个回答

5
我能找到一个不错的解决方案。 这个Lasse V. Karlsen的评论给了我灵感,再在这个领域里搜索了一下。
C# 代码:
        public static void Main(string[] args)
        {
#if MYVAR
            Log.Information("MYVAR defined!");
#else
            Log.Information("MYVAR not defined!");
#endif
        }

项目文件:

<PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <DefineConstants>$(MyVar)</DefineConstants>
</PropertyGroup>

命令:

dotnet build MyProject.csproj -p:MyVar=$MYVAR -c Debug
dotnet run --project=MyProject.csproj -c Debug --no-build

这些命令也可以使用(docker准备就绪):

dotnet publish MyProject.csproj -c Release -p:MyVar=$MYVAR
dotnet MyProject.dll
Explanation:

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

如果环境变量 $MYVAR 没有被设置(即为空字符串)或被设置为任何与 MYVAR 不同的值,则预处理器将评估条件为假。

我认为这是一个非常好的调整,适用于不同的场景。感谢你们的指导。干杯。

Note:

如问题所述,我不关心环境变量的值,只关心它是否被定义,即它要么是空字符串,要么不存在。此外,C# 代码只是 PoC,因此使用日志记录而不是编写属性和反射更容易些。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接