.NET探索平台条件编译

前言

今天偶然机会,翻了一下大学期间的书籍《C程序设计》,好吧,当我翻着翻着,翻到了符号常量(#define指令)中,是啊,这是一个预处理器指令,记得在Magicodes.IE中针对平台选择不一样的库,哈哈,这是一个典型的根据平台进行条件处理,好吧,根据这些内容,让我感受在今天,我须要对#define指令以及在.NET中的平台条件处理,以及平台的条件编译进行记录一下。html

file

define

咱们可经过define来定义符号,而后将符号用在#if指令表达式中,以下所示:git

#define PI

经过上面这些内容可能很难去了解这该如何使用,其实#define在咱们的编码过程当中也是不多去使用的,咱们继续往下看。github

其实对于预处理器,在咱们调试以及运行时的做用是比较大的,好比说对某些代码限制编译,另外一方变其实还能够对代码进行环境或者版本的控制,这些都是Ok的,最后咱们结合着控制语句#if来看一下:post

#define PI
using System;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            #if (PI)
            Console.WriteLine("PI is defined");
            #else
            Console.WriteLine("PI is not defined");
            #endif
            Console.ReadKey();
        }
    }
}

当咱们的头部声明#define PI时,咱们也能够看到编译的感知功能能够为咱们将控制语句进行切换,是啊,咱们能够在头部进行声明。测试

条件编译符号

对于上面咱们能够直接经过#define去进行条件编译,而对于在.cs文件中咱们去定义它达到的只是局部的使用,咱们若是说想全局的控制,全局的应用该如何操做?其实咱们是能够经过DefineConstants属性进行操做。ui

file

咱们能够打开项目文件进行查看,属性以下所示:编码

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5</TargetFramework>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DefineConstants>TRACE;PI</DefineConstants>
  </PropertyGroup>
</Project>

固然了,咱们一方面是可经过VS对项目的属性进行编辑,而另外一方面,咱们是可经过直接对项目文件进行修改编辑操做.这样其实达到了一个可控制性.spa

RuntimeInformation

对于代码中也是能够进行平台的逻辑判断的,在.NET Core 1.0的时候其实已经添加了System.Runtime.InteropServices.RuntimeInformation对于这个类的添加,使咱们能够动态的去判断当前的操做系统(OS),以及咱们可经过这些动态判断为咱们的业务逻辑进行不一样的处理行为。操作系统

判断当前操做系统以下所示:设计

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
    Console.WriteLine("Running on Linux!");
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
    Console.WriteLine("Running on macOS!");
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    Console.WriteLine("Running on Windows!");

MSBuild & RuntimeInformation

对于条件编译,以前咱们已经手动的操做过一次了,是咱们能够根据不一样的环境值进行对代码编译内容的控制,若是说我想根据当前的操做系统(OS)动态的进行条件编译,该如何进行操做。

其实咱们在项目文件中进行调用System.Runtime.InteropServices.RuntimeInformation进行咱们的条件处理。下面咱们看一下在MSBuild中如何调用System.Runtime.InteropServices.RuntimeInformation以下所示:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5</TargetFramework>
    <IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
    <IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
    <IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
  </PropertyGroup>

  <Target Name="PrintRID" BeforeTargets="Build">
    <Message Text="IsWindows $(IsWindows)" Importance="high" />
    <Message Text="IsOSX $(IsOSX)" Importance="high" />
    <Message Text="IsLinux $(IsLinux)" Importance="high" />
  </Target>

</Project>

咱们是能够经过visual studio或者说经过CLI直接运行构建命令dotnet build,咱们在Windows操做系统中测试一下,输出结果以下所示:

C:\Users\hueif\source\repos\ConsoleApp2\ConsoleApp2>dotnet build
用于 .NET 的 Microsoft (R) 生成引擎版本 16.8.0+126527ff1
版权全部(C) Microsoft Corporation。保留全部权利。

  正在肯定要还原的项目…
  全部项目均是最新的,没法还原。
  你正在使用 .NET 的预览版。请查看 https://aka.ms/dotnet-core-preview
  ConsoleApp2 -> C:\Users\hueif\source\repos\ConsoleApp2\ConsoleApp2\bin\Debug\net5\ConsoleApp2.dll
  IsWindows true
  IsOSX
  IsLinux

能够看出,在IsWindows中对应着true,说明咱们的操做生效了,那么咱们继续修改咱们的程序,看看如何使用条件编译,去控制咱们的代码,咱们在项目文件中添加以下片断:

<PropertyGroup Condition="'$(IsWindows)'=='true'">
    <DefineConstants>Windows</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition="'$(IsOSX)'=='true'">
    <DefineConstants>OSX</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition="'$(IsLinux)'=='true'">
    <DefineConstants>Linux</DefineConstants>
  </PropertyGroup>

经过如上语句,咱们能够对DefineConstants属性进行条件判断,条件性处理,一样咱们在代码中也是经过该值进行判断,以下所示:

static void Main(string[] args)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                Console.WriteLine("Running on Linux!");
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                Console.WriteLine("Running on macOS!");
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                Console.WriteLine("Running on Windows!");

            #if Linux
                    Console.WriteLine("Build on Linux!"); 
            #elif OSX
                    Console.WriteLine("Build on macOS!"); 
            #elif Windows
            Console.WriteLine("Build in Windows!");
            #endif
            Console.ReadKey();
        }

下面咱们来验证一下结果,是否跟咱们想象中的同样

Running on Windows!
Build in Windows!

结果没问题,已达到预期的效果。

References

https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/preprocessor-directives/preprocessor-define

https://blog.walterlv.com/post/how-to-define-preprocessor-symbols.html

相关文章
相关标签/搜索