[连载]《C#通讯(串口和网络)框架的设计与实现》- 7.外部接口的设计

简介: 目       录 第七章           外部接口的设计... 2 7.1           插件接口... 2 7.2           图形显示接口... 3 7.3           数据导出接口.

目       录

第七章           外部接口的设计... 2

7.1           插件接口... 2

7.2           图形显示接口... 3

7.3           数据导出接口... 5

7.4           服务组件接口... 6

7.5           插件管理器... 8

7.6           框架整合、重构... 9

7.7           小结... 10

第七章     外部接口的设计

开发者不仅可以二次开发设备驱动,还可以二次开发自定义图形显示形式、

自定义数据导出格式和多种业务服务,并且设备驱动接口与这三种接口进行事件响应和数据交互。

7.1    插件接口

    图形显示接口、数据导出接口和服务组件接口都继承自统一的插件接口(IPlugins),主要是方便管理和扩展。插件接口的代码定义如下:

public interface IPlugins : IDisposable
{
       /// <summary>
       /// 服务Key,要求唯一
       /// </summary>
       string ThisKey { get; }

       /// <summary>
       /// 服务名称
       /// </summary>
       string ThisName { get; }

       /// <summary>
       /// 更新设备数据,用于接收来自设备驱动的数据信息
       /// </summary>
       /// <param name="devid">设备ID</param>
       /// <param name="obj">设备对象</param>
       void UpdateDevice(int devid, object obj);

       /// <summary>
       /// 移除设备,当框架平台删除设备的时候进行响应。
       /// </summary>
       /// <param name="devid">设备ID</param>
       void RemoveDevice(int devid);
}

     图形显示接口、数据导出接口和服务组件接口与插件接口的继承关系如下图:

 

     设备驱动只要有更新数据就会通过事件把数据传送到UpdateDevice接口里,这个接口内部到底怎么处理完全由二次开发者来决定。当触发设备驱动的删除事件,就会调用RemoveDevice接口,以删除、释放资源。

7.2    图形显示接口

    框架平台通讯设备驱动把数据采集上来的只是原始数据,经过处理后要形成业务数据,那么就会有显示、分析、查询、打印、报表等业务功能,并且针对同样的数据信息,不同的用户要求处理的方式有很大的不同。这部分功能变动很大,但是又不能每次有变动就要去修改框架平台,因为框架是“稳定”的部分,形成版本控制后就不随便改变了。

   基于这样考虑,作为框架要提供一个机制,能够加载二次开发者设计的UI窗体。用于显示采集终端设备的数据,可以把不同类型设备的数据以多种形式集成显示在不同界面上。方便为用户提供多种的、更友好的人机交互界面。

   首先,框架平台不能在启动的时候就显示所有UI窗体,具体要显示哪个UI窗体完全由用户自己决定,所以,我们要通过配置文件的形式把二次开发的组件信息加载到菜单里,提供可触发的显示事件入口,如下图:

 

   其次,那么以什么样的形式显示窗体呢?像很多管理系统一样,我们采用Form Tab的方式显示,如下图:

 

   UI部分的设计就这样了,但是从业务角度我们要考虑两件事:(1)在二次开发的窗体上单击鼠标右键事件时要显示相应设备的上下文菜单,也就是说要调用IRunDevice设备驱动的ShowContextMenu函数,要在IGraphicsShow接口中提供MouseRightContextMenuHandler事件,以驱动调用ShowContextMenu函数显示上下文菜单。(2)当单击菜单项的时候,会以Tab的形式显示窗体,但是当多次单击后是不能多次显示UI窗体的,所以要有一个管理器(GraphicsShowController),通过接口的ThisKey属性判断当前显示的UI窗体是否存在,如果不存在,那么就显示该UI窗体,否则退出操作;既然有一个管理器,当关闭窗体的时候,需要把该UI窗体实例从管理器中删除掉,避免无法再次显示窗体,因为它一直存在于管理器中。所以还需要在接口中定义一个关闭窗体的事件GraphicsShowClosedHandler,释放窗体资源后从管理器中删除实例。

   至此,自定义窗体显示部分就设计完毕了,IGraphicsShow接口定义代码如下:

public interface IGraphicsShow : IPlugins
{
       /// <summary>
       ///    关闭窗体事件时发生
       /// </summary>
       event GraphicsShowClosedHandler GraphicsShowClosedHandler;
 
       /// <summary>
       ///     单击右键
       /// </summary>
       event MouseRightContextMenuHandler MouseRightContextMenuHandler;
}

7.3    数据导出接口

    在数据集成系统项目中,要么是集成其他厂家的设备数据,要么是其他厂家集成自己家的设备数据,在没有统一的标准前提下,会有各种集成数据的格式。为了满足此类的场景,为设备导出数据专门设计了接口,开发者可以继承该接口,设备在处理完数据后,会把数据自动传输到该接口,可以按规定的数据格式进行输出了。

     对设备驱动实时数据导出,可以把一类的设备数据导出成多种数据格式。

     导出数据插件可以通过配置文件进行加载,只要设备驱动有数据更新,就把数据通过事件传递给导出数据接口。不在配置文件中配置插件信息,则程序不进行加载,不进行导出操作。所以,这种事务性的服务不需要界面来完成,可以在宿主程序启动时通过代码来完成。

    IExportData数据导出接口代码定义如下:

public interface IExportData:IPlugins
{
       /// <summary>
       /// 格式化数据
       /// </summary>
       /// <param name="devid"></param>
       /// <param name="obj"></param>
       /// <returns></returns>
       object FormatDataString(int devid, object obj, DeviceType devicetype);
}

7.4    服务组件接口

     围绕着设备驱动模块采集的数据,根据应用场、需求,可以提供多种应用服务,例如:数据转发服务、4-20mA服务、短信服务、LED服务、OPC服务、以及复杂的实时数据分析服务等。在保障数据实时性、稳定性的前提下,服务接口可以提供统一的服务机制,方便开发者进行二次开发。

     服务插件的服务方式,这种服务是长期运行的事务性任务,所以更复杂一些。

    有些服务需要随宿主程序启动而自动运行,有些服务需要人工手动启动才运行。在宿主程序启动的时候通过配制文件要把服务的信息加载到菜单上,菜单里显示的服务可能有些已经启动了;有些需要通过单击操作,显示窗体并填写必要的信息后才可能启动。所以,宿主程序与服务插件不是单向交互,而是双向数据、事件交互。

    IappService服务接口在IPlugins基础上进行扩展,增加了函数、属性和事件,代码定义如下:

public interface IAppService : IPlugins
{
        /// <summary>
       ///     启动服务
       /// </summary>
       void StartService();

       /// <summary>
       ///     是否自动启动
       /// </summary>
       bool IsAutoStart { set; get; }
      
         /// <summary>
       ///     服务类型
       /// </summary>
       ServiceType ServiceType { set; get; }

       /// <summary>
       ///     单击事件,关联菜单
       /// </summary>
       void OnClick();

       /// <summary>
       ///     释放服务
       /// </summary>
       void ReleaseService();

       /// <summary>
       ///     写日志事件
       /// </summary>
       event WriteLogHandler WriteLogHandler;
}

(1)    StartService函数:当服务的启动方式(IsAutoStart)为"自动启动"的时候,框架平台在加载服务的时候,会自动调用这个接口函数,表示对服务进行启动操作。

(2)    IsAutoStart属性:服务启动类型,标识是否随框架平台启动而自动启动,也就是标识是否会调用StartService接口函数。

(3)    ServiceType属性:服务类型分为:显示模式和隐藏模式。显示模式的服务会在框架平台的菜单上加载以ThisName标识的服务名称;隐藏模式不会在框架平台的菜单中加载服务名称,可以把此类服务的IsAutoStart属性设置为自动启动,框架平台启动后自动启动服务。代码定义如下:

public enum ServiceType
{
    [EnumDescription("显示模式")]
    Show = 0x00,
    [EnumDescription("隐藏模式")]
    Hide = 0x01
}

(4)    OnClick事件函数:当服务类型ServiceType为“显示模式“的时候,服务名称会被加载到菜单中,当单击服务菜单项的时候,会调用相应服务的OnClick接口函数,可以在这个接口函数里调用窗体。

(5)    ReleaseService函数:当关闭框架平台和人工手动停止服务后,可以通过这个函数释放服务资源。

 另外,对于服务组件接口还涉及到服务状态,标识服务在运行的过程中处

于什么阶段,例如:服务正在启动、服务已经启动、服务正在运行、服务正在终止、服务已经终止等等。因为根据服务的事务复杂度不同,服务的状态也可能不同,所以服务状态的定义交给了二次开发者自己定义。

7.5    插件管理器

    图形显示接口、数据导出接口和服务组件接口都分别有一个接口管理器,负责对各功能接口进行管理,它们都继承自IBaseManager<TKey, TValue>接口。继承关系图如下:

 

7.6    框架整合、重构

    总的来说,框架平台涉及到四个主要的接口:IRunDevice设备驱动接口、IGraphicsShow图形显示接口、IExportData数据导出接口和IAppService服务组件接口。它们现在的继承结构关系如下图:

 

实际上继承这四个接口二次开发的模块都是以插件的形式加载到框架平台,框架平台在结构上实现了一整套的运行机制。对上面的继承关系结构图进行分析,还有整合、重构的余地,进一步明晰接口关系、整合代码,提高框架的可扩展性,计划重构后的接口继承关系如下图:

 

     所有可扩展的接口都继承自一个插件接口,再分支出来其他的业务功能接口,类似于C#语言中所有实体都继承自Object一样。

7.7    小结

    框架内部实际上是对接口进行直接调用,接口与接口之间的配合又实现了一套协调机制,从而逐步实现了一个框架平台。作为接口实际上是实现了二次开发与框架平台对接的一种形式,并保证在框架平台的协调机制中实现特定的业务功能。所以,任何框架,从顶层来看都是对接口的设计。

 

作者:唯笑志在

mail:504547114@qq.com

QQ:504547114

.NET开发技术联盟:54256083

文档下载:http://pan.baidu.com/s/1pJ7lZWf

官方网址:http://www.bmpj.net

相关文章
|
3月前
|
监控 安全
从 Racket 语言出发,创新员工网络监控软件的框架
在数字化企业环境中,员工网络监控软件对于保障信息安全和提升效率至关重要。Racket 语言凭借其独特特性和强大功能,为开发创新的监控软件提供了新可能。通过捕获和分析网络数据包、记录员工网络活动日志,甚至构建复杂的监控框架,Racket 能够满足企业的定制化需求,为企业信息安全和管理提供强有力支持。未来,基于 Racket 的创新解决方案将不断涌现。
46 6
|
2月前
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
118 6
|
3月前
|
机器学习/深度学习 人工智能
类人神经网络再进一步!DeepMind最新50页论文提出AligNet框架:用层次化视觉概念对齐人类
【10月更文挑战第18天】这篇论文提出了一种名为AligNet的框架,旨在通过将人类知识注入神经网络来解决其与人类认知的不匹配问题。AligNet通过训练教师模型模仿人类判断,并将人类化的结构和知识转移至预训练的视觉模型中,从而提高模型在多种任务上的泛化能力和稳健性。实验结果表明,人类对齐的模型在相似性任务和出分布情况下表现更佳。
80 3
|
3月前
|
安全 网络安全 区块链
网络安全与信息安全:构建数字世界的防线在当今数字化时代,网络安全已成为维护个人隐私、企业机密和国家安全的重要屏障。随着网络攻击手段的不断升级,从社交工程到先进的持续性威胁(APT),我们必须采取更加严密的防护措施。本文将深入探讨网络安全漏洞的形成原因、加密技术的应用以及提高公众安全意识的重要性,旨在为读者提供一个全面的网络安全知识框架。
在这个数字信息日益膨胀的时代,网络安全问题成为了每一个网民不可忽视的重大议题。从个人信息泄露到企业数据被盗,再到国家安全受到威胁,网络安全漏洞如同隐藏在暗处的“黑洞”,时刻准备吞噬掉我们的信息安全。而加密技术作为守护网络安全的重要工具之一,其重要性不言而喻。同时,提高公众的安全意识,也是防范网络风险的关键所在。本文将从网络安全漏洞的定义及成因出发,解析当前主流的加密技术,并强调提升安全意识的必要性,为读者提供一份详尽的网络安全指南。
|
4月前
|
存储 SQL 安全
网络安全与信息安全:守护数字世界的坚盾在这个高度数字化的时代,网络安全和信息安全已经成为个人、企业乃至国家安全的重要组成部分。本文将深入探讨网络安全漏洞、加密技术以及安全意识的重要性,旨在为读者提供一个全面的网络安全知识框架。
随着互联网技术的飞速发展,网络安全问题日益凸显。从个人信息泄露到企业数据被盗,再到国家安全受到威胁,网络安全事件层出不穷。本文将从网络安全漏洞的定义与分类入手,探讨常见的网络攻击手段;随后深入解析加密技术的原理及其在保护信息安全中的作用;最后强调提升公众与企业的安全意识的重要性,并提出具体的建议。通过综合运用这些知识点,我们可以更好地构建起一道道坚固的防线,守护我们的数字世界。
|
19天前
|
机器学习/深度学习 算法 PyTorch
基于图神经网络的大语言模型检索增强生成框架研究:面向知识图谱推理的优化与扩展
本文探讨了图神经网络(GNN)与大型语言模型(LLM)结合在知识图谱问答中的应用。研究首先基于G-Retriever构建了探索性模型,然后深入分析了GNN-RAG架构,通过敏感性研究和架构改进,显著提升了模型的推理能力和答案质量。实验结果表明,改进后的模型在多个评估指标上取得了显著提升,特别是在精确率和召回率方面。最后,文章提出了反思机制和教师网络的概念,进一步增强了模型的推理能力。
48 4
基于图神经网络的大语言模型检索增强生成框架研究:面向知识图谱推理的优化与扩展
|
20天前
|
开发框架 监控 .NET
C#进阶-ASP.NET WebForms调用ASMX的WebService接口
通过本文的介绍,希望您能深入理解并掌握ASP.NET WebForms中调用ASMX WebService接口的方法和技巧,并在实际项目中灵活运用这些技术,提高开发效率和应用性能。
38 5
|
2月前
|
人工智能 自然语言处理
WebDreamer:基于大语言模型模拟网页交互增强网络规划能力的框架
WebDreamer是一个基于大型语言模型(LLMs)的网络智能体框架,通过模拟网页交互来增强网络规划能力。它利用GPT-4o作为世界模型,预测用户行为及其结果,优化决策过程,提高性能和安全性。WebDreamer的核心在于“做梦”概念,即在实际采取行动前,用LLM预测每个可能步骤的结果,并选择最有可能实现目标的行动。
64 1
WebDreamer:基于大语言模型模拟网页交互增强网络规划能力的框架
|
2月前
|
JSON 数据处理 Swift
Swift 中的网络编程,主要介绍了 URLSession 和 Alamofire 两大框架的特点、用法及实际应用
本文深入探讨了 Swift 中的网络编程,主要介绍了 URLSession 和 Alamofire 两大框架的特点、用法及实际应用。URLSession 由苹果提供,支持底层网络控制;Alamofire 则是在 URLSession 基础上增加了更简洁的接口和功能扩展。文章通过具体案例对比了两者的使用方法,帮助开发者根据需求选择合适的网络编程工具。
36 3
|
2月前
|
存储 安全 网络安全
网络安全法律框架:全球视角下的合规性分析
网络安全法律框架:全球视角下的合规性分析
57 1