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

Posted

技术标签:

【中文标题】基于 NuGet PackageReference 定义一个 C# 预处理器符号【英文标题】:Define a C# preprocessor symbol based on NuGet PackageReference 【发布时间】:2020-10-01 10:22:04 【问题描述】:

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

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

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

除非这不起作用。

【问题讨论】:

【参考方案1】:

一种自动执行此类操作的方法是包含一个目标,该目标将构建逻辑贡献到您的 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>

通过挂钩到构建过程,这可以检测您的代码是否对特定 NuGet 包有任何编译时引用(意味着包的 API 表面在您的 C# 代码中可用),即使它们只是被传递引用(例如您引用了一个引用 Newtonsoft.Json 的库,以便您可以使用它)。

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

【讨论】:

抱歉耽搁了,很好的回答!【参考方案2】:

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

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

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

【讨论】:

是的,对不起,我应该更清楚。当 PackageReference 存在时,我想“自动”添加它们。 据我所知,Nuget Packages 没有“自动”Preprocessor Directive 但是,我不得不提到Cake.Recipe 的一些选项。 (例如加载项指令)。 cakebuild.net/docs/fundamentals/preprocessor-directives

以上是关于基于 NuGet PackageReference 定义一个 C# 预处理器符号的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将 OctoPack 与新的 PackageReference NuGet 格式一起使用?

如何强制降级 dotnet core 中的传递依赖

获取NuGet包的位置

.NET6打包部署到Windows Service

Roslyn 打包 NuGet 包 BuildTransitive 文件夹用于穿透依赖传递拷贝文件

EFcore 数据迁移