我可以根据 .NET Core 中的运行时标识符定义常量吗?

Can I define constants based on the runtime identifier in .NET Core?

我有一个 .NET Core 控制台应用程序。我的目标是能够有条件地 DLLImport 一个函数并调用它,但仅限于 Windows 运行时。

我想也许如果我可以访问 csproj 文件中的运行时标识符,我可以有条件地为该运行时定义一个常量,然后在我的 c# 中我可以包围 DLLImport 并调用 #if/#endif 块。

是否可以根据正在构建项目的运行时在 csproj 中设置编译常量?这是专门针对 .NET Core 的 SDK 样式项目格式(以 <Project Sdk="Microsoft.NET.Sdk"> 开头)。

注意: 接近,但适用于 project.json 风格的项目。

或者,是否有更好的方法来实现我的目标?

如果您通过传递不同的 --runtime 选项 (MSBuild 属性 RuntimeIdentifier) 构建和发布不同的 运行 次,您可以 属性 在 csproj 文件中(允许您在 C# 代码中使用 #if BUILT_FOR_WINDOWS):

<PropertyGroup>
  <DefineConstants Condition="'$(RuntimeIdentifier)' == 'win-x64'">$(DefineConstants);BUILT_FOR_WINDOWS</DefineConstants>
</PropertyGroup>

但是您也可以在 运行 时间使用以下方法测试当前 OS:

using System.Runtime.InteropServices;
…

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
    // call windows function here
}
else
{
    // do something else here
}

只要标有[DllImport(…)]的函数不在找不到库/方法的OS上调用,就不会有任何问题。请注意 DllImport() 也可以根据 os 探测不同的库 - 所以 DllImport("foo") 会检查 foo.dllfoo.dyliblibfoo.so 等.

添加到 Martin Ullrich 的回答:如果您想在引用的库项目中基于 RuntimeIdentifier 定义常量,而不是在具有应用程序入口点的项目中,请确保包含您所使用的标识符列表在项目的 .csproj 文件中的 RuntimeIdentifiers 属性 中使用,例如:

<PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <RuntimeIdentifiers>linux-x64;linux-arm</RuntimeIdentifiers>
</PropertyGroup>

如果您不这样做,那么常量将不会被定义为 RuntimeIdentifier 属性 将不会像我的情况一样传递给 csproj。

来源:https://github.com/dotnet/core/issues/2678#issuecomment-498967871