[连载]《C#通讯(串口和网络)框架的设计与实现》- 7.外部接口的设计
目 录
第七章 外部接口的设计... 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
[连载]《C#通讯(串口和网络)框架的设计与实现》- 7.外部接口的设计的更多相关文章
- [连载]《C#通讯(串口和网络)框架的设计与实现》- 0.前言
目 录 前言 前言 刚参加工作,使用过VB.VC开发软件,随着C#的崛起,听说是C++++,公司决定以后开发软件使用C#,凭借在 ...
- 《连载 | 物联网框架ServerSuperIO教程》-4.如开发一套设备驱动,同时支持串口和网络通讯。附:将来支持Windows 10 IOT
1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》-1.通讯框架介绍
[连载]<C#通讯(串口和网络)框架的设计与实现>- 0.前言 目 录 第一章 通讯框架介绍... 2 1.1 通讯的本质... 2 1 ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》- 6.通讯控制器的设计
目 录 第六章 通讯控制器的设计... 2 6.1 控制器接口... 2 6.2 串口控制器... 3 6.3 ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》-2.框架的总体设计
目 录 C#通讯(串口和网络)框架的设计与实现... 1 (SuperIO)- 框架的总体设计... 1 第二章 框架总体的设计... 2 2.1 ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》- 5.串口和网络统一IO设计
目 录 第五章 串口和网络统一IO设计... 2 5.1 统一IO接口... 2 5.1.1 串口IO.. 4 5.1.2 网络IO.. ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》-4.设备驱动管理器的设计
目 录 第四章 设备驱动管理器的设计... 2 4.1 接口定义... 2 4.2 设备容器... 7 4.3 ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》-3.设备驱动的设计
目 录 第三章 设备驱动的设计... 2 3.1 初始化设备... 4 3.2 运行设备接口设计... 4 3.3 ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》- 10.宿主程序详细设计
目 录 第十章 宿主程序详细设计... 2 10.1 配置文件设计... 3 10.2 加载设备驱动... 4 10.3 加载 ...
随机推荐
- celery使用的一些小坑和技巧(非从无到有的过程)
纯粹是记录一下自己在刚开始使用的时候遇到的一些坑,以及自己是怎样通过配合redis来解决问题的.文章分为三个部分,一是怎样跑起来,并且怎样监控相关的队列和任务:二是遇到的几个坑:三是给一些自己配合re ...
- Android 解析XML文件和生成XML文件
解析XML文件 public static void initXML(Context context) { //can't create in /data/media/0 because permis ...
- android计算每个目录剩余空间丶总空间以及SD卡剩余空间
ublic class MemorySpaceCheck { /** * 计算剩余空间 * @param path * @return */ public static String getAvail ...
- AEAI DP V3.6.0 升级说明,开源综合应用开发平台
AEAI DP综合应用开发平台是一款扩展开发工具,专门用于开发MIS类的Java Web应用,本次发版的AEAI DP_v3.6.0版本为AEAI DP _v3.5.0版本的升级版本,该产品现已开源并 ...
- WINDOWS系统下MYSQL安装过程中的注意事项
1.首先MySQL的安装方式有两种:一种是MSI安装方式,很简单就像安装Windows软件一样.另外一种就是ZIP安装方式.这种相对而言比较麻烦.新手推荐MSI安装方式. 安装方式有以下两种: MSI ...
- 二次剩余、三次剩余、k次剩余
今天研究了一下这块内容...首先是板子 #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- embedding mono实战笔录(一)
最近在给自己的服务器节点添加脚本功能,考虑到 执行性能.开发效率.调试效率.可维护性.严谨性 五大要素,最终选用C#作为脚本语言,并使用mono作为中间层,使其具备跨平台特性,以备具有在Windows ...
- 一步步学习javascript基础篇(9):ajax请求的回退
需求1: ajax异步请求 url标识请求参数(也就是说复制url在新页面打开也会是ajax后的效果) ajax异步请求没问题,问题一般出在刷新url后请求的数据没了,这就是因为url没有记录参数.如 ...
- Running Dubbo On Spring Boot
Dubbo(http://dubbo.io/) 是阿里的开源的一款分布式服务框架.而Spring Boot则是Spring社区这两年致力于打造的简化Java配置的微服务框架. 利用他们各自优势,配置到 ...
- 一种简单,轻量,灵活的C#对象转Json对象的方案(续)
本文参考资料 一种简单,轻量,灵活的C#对象转Json对象的方案 [源码]Literacy 快速反射读写对象属性,字段 一段废话 之前我已经介绍了这个方案的名称为JsonBuilder,这套方案最大的 ...