定义基于 NuGet PackageReference 的 C# 预处理器符号

Define a C# preprocessor symbol based on NuGet PackageReference

当(且仅当)Newtonsoft.Json NuGet 包作为 PackageReference 添加到我的 .NET Core 应用程序时,我想定义一个符号 NEWTONSOFT。我该怎么做?

编辑:为澄清起见,如果存在引用,我想添加符号。如果我删除引用,则不应再定义符号 - 但我不应该手动 add/remove 符号定义。像这样:

<Choose>
    <When Condition=" '$(PackageReference).Identity'=='Newtonsoft.Json' ">
        <PropertyGroup>
            <DefineConstants>HDN</DefineConstants>
        </PropertyGroup>
    </When>
</Choose>

除此之外不起作用。

您可以在 Project PropertiesDebug 选项卡中添加 Conditional compilation symbols 并像这样使用 Roslyn 预处理器指令:

#if NEWTONSOFT && !JSON.NET
// Your Codes
#endif

根据 Microsoft Docs,您没有任何 Nuget 包的预处理器指令。

一种自动执行此类操作的方法是将构建逻辑添加到您的 csproj 文件中,如下所示:

<Target Name="AddPackageSpecificConstants" BeforeTargets="BeforeCompile">
  <PropertyGroup>
    <DefineConstants Condition="@(Reference->AnyHaveMetadataValue('NuGetPackageId','Newtonsoft.Json'))">$(DefineConstants);NEWTONSOFT_JSON</DefineConstants>
    <DefineConstants Condition="@(Reference->AnyHaveMetadataValue('NuGetPackageId','YamlDotNet '))">$(DefineConstants);YAML_DOT_NET</DefineConstants>
  </PropertyGroup>
</Target>

通过挂接到构建过程,这可以检测您的代码是否有任何 compile-time 引用(意味着包的 API 表面在您的 C# 代码中可用)到特定的 NuGet 包,甚至如果它们仅被传递引用(例如,您引用了一个引用 Newtonsoft.Json 的库,以便您可以使用它)。

通过像 <X>$(X);</X> 这样的定义,额外的常量被添加到 属性 中,因此 SDK 根据目标框架或您的其他项目内容默认为您提供的任何内容都保持不变。