前言

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

根据这些内容,让我感觉在今天,我需要对#define指令以及在.NET中的平台条件处理,以及平台的条件编译进行记录一下。

define

我们可通过define来定义符号,然后将符号用在#if指令表达式中,如下所示:

#define PI

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

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

#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属性进行操作。

我们可以打开项目文件进行查看,属性如下所示:

<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对项目的属性进行编辑,而另一方面,我们是可通过直接对项目文件进行修改编辑操作.这样其实达到了一个可控制性.

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

.NET探索平台条件编译的更多相关文章

  1. ZTESoft 持续集成 编年史 之 持续集成探索---平台选择

    2012 年 7.8 月份,我们逐渐了解了持续集成的概念,同时我们家庭作坊的dailybuild方式不断爆出各种问题,并且已经无法满足日益增长的各种需求. 我们开始探索持续集成的不同实现方式,首先我们 ...

  2. 百度 LBS 开放平台,开发人员众測计划正式启动

    Hi各位亲爱滴开发人员:   你是否以前-- 期望第一时间率先接触到百度LBS开放平台的最新功能? 期望被邀请作为最最尊贵的首批试用志愿者感受志愿者的特权? 期望自己的意见被产品经理採纳.优化功能.从 ...

  3. 关于页ASP.NET面布局

    关于页面布局,充分利用Table和分层   从接触ASP.NET到现在已经有一段时间了,起初总是嫌麻烦,想找捷径,凡是想当然,结果导致自己反而走了不少的弯路. 起初刚开始接触ASP.NET的时候,发现 ...

  4. Web工程师必备的43款可视化工具

    国外站点DATAVISUALIZATION.CH为大家总结出了当前热用的43款可视化工具,包括Arbor.Chroma.js.D3.js.Google Chart Tools等,绝对让你一饱眼福. 1 ...

  5. 迎战大数据-Oracle篇

    来自:http://www.cnblogs.com/wenllsz/archive/2012/11/16/2774205.html 了解大数据带来的机遇: 透视架构与工具: 开源节流,获得竞争优势. ...

  6. 优化基于FPGA的深度卷积神经网络的加速器设计

    英文论文链接:http://cadlab.cs.ucla.edu/~cong/slides/fpga2015_chen.pdf 翻译:卜居 转载请注明出处:http://blog.csdn.net/k ...

  7. win8.1和wp8.1共用代码,需要注意的一些问题

    最近写了一个应有,使用了mvvmlight,把viewmodel.model.common之类的代码都放到了shared共享,写下来才发现,有不少问题是自已下手之前没注意到的,有些地方实在没法中途改了 ...

  8. R in action读书笔记(22)第十六章 高级图形进阶(下)

    16.2.4 图形参数 在lattice图形中,lattice函数默认的图形参数包含在一个很大的列表对象中,你可通过trellis.par.get()函数来获取,并用trellis.par.set() ...

  9. [AIR] as3 之条件编译多平台妙用

    http://bbs.9ria.com/thread-418864-1-1.html 一直希望as3 可以支持条件编译,即满足A时编译函数1,满足B时则编译函数2. 最佳百度了之后,发现原来是可以实现 ...

随机推荐

  1. 深入理解Java虚拟机(二)——HotSpot对象创建、内存、访问

    对象的创建 虚拟机遇到一条字节码new指令时,开始对象创建过程. 首先去检查这个指令的参数是否能在常量池定位到一个类的符号引用: 检查这个符号引用代表的类是否已被加载.解析和初始化,如果没有就必须执行 ...

  2. 六、Zookeeper-开源客户端ZkClient与Curator

    ZkClient 从创建会话.创建节点.读取数据.更新数据.删除节点拉介绍ZkClient 添加依赖: pom.xml <dependency> <groupId>com.10 ...

  3. AOP 有几种实现方式?

    1. 回顾 AOP 是什么? 维基百科解释如下: 面向切面的程序设计(Aspect-oriented programming,AOP,又译作面向方面的程序设计.剖面导向程序设计)是计算机科学中的一种程 ...

  4. windows远程msra windows使用技巧

    qq远程太慢,mstsc?又不想把电脑密码告诉好友,怎么办呢?在这里推荐一个方法: 点击开始运行输入msra,确定,邀请信任的人帮助你您,将该邀请另存为文件,然后这个窗口不要关,把密码复制粘贴给好友, ...

  5. Oracle数据导入Mysql中

    一.Navicat Premium中的数据迁移工具 为了生产库释放部分资源,需要将API模块迁移到mysql中,及需要导数据. 尝试了oracle to mysql工具,迁移时报错不说,这么大的数据量 ...

  6. 持久层之 MyBatis: 第二篇 :动态SQL And多表查询

    MyBatis入门到精通 完整CRUD UserDaoImpl 编写UserDao对应的UserDaoMapper.xml 添加UserDao的测试用例 编写UserDao的测试用例 解决数据库字段名 ...

  7. UWP 自定义RadioButton实现Tab底部导航

    先看效果: 参照Android的实现方式用RadioButton来实现,但是Uwp的RadioButton并没有安卓的Selector选择器 下面是一个比较简单的实现,如果有同学有更好的实现,欢迎留言 ...

  8. webform中DropdownList绑定多个字段

    说明 ListItem中有Attributes属性,手动创建一个自定义属性,赋值需要绑定的字段的值. 这样的话,前台js也可以获取到,能够显示到前台html,进行控制. 代码 foreach(Data ...

  9. 我都xxx岁了,还能继续做开发吗?

    前言 今天纯文字,阅读时间10分钟左右 最近在看一本书<大型网站技术架构:核心原理与案例分析>,可以说是非常枯燥的一本书,在开头几章讲解了网站的发展,介绍了一些架构中的常用名词.虽然有点枯 ...

  10. C语言实现汉诺塔

    汉诺塔 要把A柱子上的盘子移动到C柱子上,在移动过程中可以借助B柱子,但是要求小的盘子在上大的盘子在下. 解题思路: 1.把A柱子上的前N-1个盘子借助C柱子,全部移动到B柱子上(过程暂不考虑),再把 ...