开源纯C#工控网关+组态软件(十)移植到.NET Core

一、   引子

写这个开源系列已经十来篇了。自从十年前注册博客园以来,关注了张善友、老赵、xiaotie、深蓝色右手等一众大牛,也围观了逗比的吉日嘎啦、精密顽石等形形色色的园友。然而整整十年一篇文章都没有写过,属于非常努力的在社区汲取营养的菜青虫一只,现在也算破茧而出了,虽然远没有得道化蝶的境界,也在写作过程中得到不少提升。我开源的这个项目也有我固有的不良代码风格:严重缺乏注释,一方面是懒,一方面因为是单兵作战,也未曾想过让别人理解自己的代码。如何用简洁明了的方式表达自己的思路,虽然烧脑,但得到了社区的初步认可,在激励我把这个系列坚持下去的同时,对下一步如何完善这个项目,思路也更加清晰了。

二、      为什么要移植到.NET Core

开源纯C#工控网关+组态软件(十)移植到.NET Core

.NET Core是.NET Framework的新一代版本,具有跨平台 (Windows、Mac OSX、Linux) 能力的应用程序开发框架。.NET Core遵循最宽松的开源协议,可以方便的移植到非微软平台,同时据说有相当出色的性能。这些已经足够吸引人了,对我这一工控狗而言,架构如果限定在Windows操作系统,有几个问题是难以解决但必须面对的:

  • 实时性

Windows是非实时的操作系统;受限于操作系统,我的网关程序始终找不到高精度的定时器,对一些实时性要求很高的场合,例如高精度机床控制,就力不从心了,而如果网关能移植到实时系统,这个问题就能得到解决。

  • 跨平台性

在一些诸如军工、机关、央企的场合都指定使用linux操作系统,如果不能跨平台,显然根本没有入局的机会。.NET Core的跨平台能力保证了广泛的适应性,起码不会因为绑定平台而被拒(杯具)。

  • 开源社区支持

因为宽松的开源协议,.NET Core现在已经成为很热门的开源项目,在社区获得了广泛的支持。最起码不用担心它的生命被微软忽然宣布死亡-微软虽然是.NET社区强有力的支持者,但不是唯一的;有谷歌,三星,Unity甚至红帽加入的.NET基金会的强大阵容;越来越多的开源社区接纳了.NET,并为之开发各种组件和应用。

  • 性能

看了不少公开资料及社区反馈,.NET Core的性能相比.NET Framework有大幅提升。部分常用类库据说提升达到60%(求证实)。但.NET Core毫无疑问是.NET 平台的未来,会得到持续的升级。

三、   如何移植

关于如何移植,博客园有不少好的文章。以我粗浅的理解和实践,就是建立一个.NET Core项目(VS017支持.NET Core 2.0),VS会自动加载相关的依赖项;将我网关部分的代码拷贝到新的文件夹下,形成下面这几个新的基于Core的项目:

开源纯C#工控网关+组态软件(十)移植到.NET Core

可以看到,Core项目没有常规的dll引用方式,而代之以“项目”引用(即同一解决方案下的项目,这点和.NET Framework类似)以及NuGet包引用。NuGet可以理解为类库“商店”,在NuGet上寻找你需要的组件和类库,基本上常用的,你觉得应该有的,都能搜到,并傻瓜式下载、安装、部署。

开源纯C#工控网关+组态软件(十)移植到.NET Core开源纯C#工控网关+组态软件(十)移植到.NET Core

和常规的.NET项目比较,基本大同小异,目标框架可选.NET Core的各版本。编译后生成的同样是dll文件,反射依然可用。另外还惊喜的发现.NET Core依然支持不安全代码-也就是支持指针,似乎说明微软设计者相当重视性能问题。

要让JAVA死忠们接受后来者.NET Core,性能优势、VS支持、部署傻瓜化这些显然很有吸引力。对我这类.NET 老用户而言,一个Core项目并没有什么违和感。一切都是亲切的老面孔,但深入之后,会发现也有一些不同之处,只是解决起来总体十分顺畅。下面说说我试手将SCADA项目的网关部分初步移植到.NET Core的过程。

四、   .NET Core填坑记

  • 移植准备

大概的学习了下.NET Core的基本概念,发现有几个重要问题必须要面对:

没有UI: Winform、WPF这一类的UI库并没有在.NET Core实现。大概是因为界面这部分各家差异太大,而且界面技术日新月异,做跨平台的界面现在流行用Web。Core只提供了简单的控制台输出显示。看来人机界面部分(HMI控件、WPF界面)目前是无法移植了。不过真正有移植价值的还是在网关部分,这部分如果能跨平台,界面用H5,WPF,还是QT都无所谓,反正都是通用的Socket通讯。(注:在最新的.NET Core 3.0版本,能够在Windows环境下兼容WPF,Winform,兼容UWP,这个消息值得期待)

没有对SQL Server的支持:大概因为SQL Server本身就不跨平台吧。这就逼得我必须寻找一个跨平台的数据库用来做系统配置和元数据存储。根据网友们的建议,我考虑 用MySQL作数据库,开源跨平台,用户多,工具完备,支持网络访问,性能也不错。好在NuGet上有不少开源类库支持对MySQL读写。

.Net Core下没有Windows 服务:原有的WCF后台服务和封装为Windows 服务组件的功能废弃,网关直接挂接一个控制台程序。需要与客户端交互,除了原有的基于Socket的TLV协议,还可以设计RESTful 调用接口,比WCF这种笨家伙只会更方便。

Windows日志的实现方式大不相同:大概为了和其他系统兼容,不能采用直接读写EventLog的方式了。SCADA项目的流水账记录和错误日志都写入Windows事件管理器,必须要替换。我比较了几种常用的日志移植方法,决定采用微    软自家的Logging组件,官方支持,同时扩展性看上去不错,最重要的是简单,写法上也和之前区别不大。另外第三方的Log4Net,NLog也移植到了.NET Core,这些日志库更为强大和专业。

没有内置串口组件:因为是工控组件,对串口的支持是必要的。但Core并没有内置SerialPort这种类库,感觉有点奇怪。在NuGet上搜到有RJCP.IO.Ports这个库,用法和SerialPort大同小异。

还有一些小功能需要移植,如读写ini配置文件等。好在NuGet上都有官方类库可用。

  • 移植过程

MySQL连接用了NuGet下载的MySQLConnector类库。开源免费,同时下载的人很多,从一个侧面印证了它的优秀。我重写了DataHelper类,使之能够实现多种数据库支持。简单起见,套用了一个数据库工厂模式,定义了一套数据读写接口。MySQLConnector比起Framework下的SqlConnector,没有什么特别的,继承的是同一套接口或抽象类,例如DbParameter、DbDataReader、DbCommand等。唯一注意的就是之前惯用的数据库批量写入类SqlBulkCopy不能再用了。MySql里有它自家的批量写入方式。

对日志的操作用了一个“提供者模式”,对于在Debug模式下有DebugLoggerProvider、控制台模式下有ConsoleLoggerProvider,设计十分合理。

对配置文件的管理用了一个构建者(Builder)模式,无论是ini配置方式还是xml配置方式都有自己的实现。

从对日志和配置的官方实现,让我感觉微软对.NET Core的设计颇为用心。在.NET FX下对配置文件或者日志的读写,要么是专门对Windows设计的EventLog日志类,要么连ini的官方支持都没有,必须调用API函数。而在Core中进行了重构,进行了合理充分的抽象,架构十分简洁明了,尤其是充分考虑了各平台对日志、配置文件的共性需求,易于扩展,也有助于开源社区自行发展完善。

  • 总体感觉

感觉Core和老的Framework还是非常相似的,起码绝大部分是兼容的。只有与操作系统和数据库密切相关的部分被重新实现了,但也很容易在NuGet找到替代办法。可以说,移植体验很顺畅。移植过程很傻瓜。让我这类初次使用者就能很快完成移植,甚至感觉Core重写之后比老的Framework代码更为简洁,架构更为清晰。这让我对Core的前景信心大增。

  • 未来改进

这次的移植只是初试,虽然编译通过并在虚拟机环境下测试,但并没在真实Linux环境下测试。因为不熟悉mysql,原有SQL SERVER的部分功能(如存储过程等)移植不全。未来我希望把网关部分也加入NuGet包,并提供支持.NET Core的设备驱动包下载,依靠开源社区使这个项目支持越来越多的系统平台、硬件设备和行业。

五、   下面的计划

写一系列帖子,把架构、原理讲清楚。大致如下:

github地址:https://github.com/GavinYellow/SharpSCADA。QQ群:102486275

上一篇:RobotFramework自动化测试框架的基础关键字(四)


下一篇:PS纯手式打造不规则颜色的规则方块—学习教程