目       录

第七章           外部接口的设计... 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.外部接口的设计的更多相关文章

  1. [连载]《C#通讯(串口和网络)框架的设计与实现》- 0.前言

                                  目       录 前言 前言 刚参加工作,使用过VB.VC开发软件,随着C#的崛起,听说是C++++,公司决定以后开发软件使用C#,凭借在 ...

  2. 《连载 | 物联网框架ServerSuperIO教程》-4.如开发一套设备驱动,同时支持串口和网络通讯。附:将来支持Windows 10 IOT

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...

  3. [连载]《C#通讯(串口和网络)框架的设计与实现》-1.通讯框架介绍

    [连载]<C#通讯(串口和网络)框架的设计与实现>- 0.前言 目       录 第一章           通讯框架介绍... 2 1.1           通讯的本质... 2 1 ...

  4. [连载]《C#通讯(串口和网络)框架的设计与实现》- 6.通讯控制器的设计

    目       录 第六章           通讯控制器的设计... 2 6.1           控制器接口... 2 6.2           串口控制器... 3 6.3          ...

  5. [连载]《C#通讯(串口和网络)框架的设计与实现》-2.框架的总体设计

    目       录 C#通讯(串口和网络)框架的设计与实现... 1 (SuperIO)- 框架的总体设计... 1 第二章           框架总体的设计... 2 2.1           ...

  6. [连载]《C#通讯(串口和网络)框架的设计与实现》- 5.串口和网络统一IO设计

    目       录 第五章           串口和网络统一IO设计... 2 5.1           统一IO接口... 2 5.1.1    串口IO.. 4 5.1.2    网络IO.. ...

  7. [连载]《C#通讯(串口和网络)框架的设计与实现》-4.设备驱动管理器的设计

    目       录 第四章           设备驱动管理器的设计... 2 4.1           接口定义... 2 4.2           设备容器... 7 4.3          ...

  8. [连载]《C#通讯(串口和网络)框架的设计与实现》-3.设备驱动的设计

    目       录 第三章           设备驱动的设计... 2 3.1           初始化设备... 4 3.2           运行设备接口设计... 4 3.3        ...

  9. [连载]《C#通讯(串口和网络)框架的设计与实现》- 10.宿主程序详细设计

    目       录 第十章           宿主程序详细设计... 2 10.1        配置文件设计... 3 10.2        加载设备驱动... 4 10.3        加载 ...

随机推荐

  1. Supermap iCloudManager -负载均衡

    Supermap icm负载均衡理解: 应用场景:地图出图 子节点1和子节点2中的服务保持一致,一般情况下设置的是匿名用户通过nginx访问服务信息,所以不需要登录. 1.通过nginx分发请求,(轮 ...

  2. Vue.js——60分钟browserify项目模板快速入门

    概述 在之前的一系列vue.js文章,我们都是用传统模式引用vue.js以及其他的js文件的,这在开发时会产生一些问题. 首先,这限定了我们的开发模式是基于页面的,而不是基于组件的,组件的所有代码都直 ...

  3. [模拟电路] 2、Passive Band Pass Filter

    note: Some articles are very good in http://www.electronics-tutorials.ws/,I share them in the Cnblog ...

  4. 详解this

    this 虐我千百遍,看完此文效立见!不得不说,这篇文章的总结很地道很全面,适合收藏之用. 原文:all this 习惯了高级语言的你或许觉得JavaScript中的this跟Java这些面向对象语言 ...

  5. 轻量级表达式树解析框架Faller

    有话说 之前我写了3篇关于表达式树解析的文章 干货!表达式树解析"框架"(1) 干货!表达式树解析"框架"(2) 干货!表达式树解析"框架" ...

  6. 牛逼的css3:动态过渡与图形变换

    写css3的属性的时候,最好加上浏览器内核标识,进行兼容. -ms-transform:scale(2,4); /* IE 9 */ -moz-transform:scale(2,4); /* Fir ...

  7. Javascript之自定义事件

    Javascript自定义事件,其本质就是观察者模式(又称订阅/发布模式),它的好处就是将绑定事件和触发事件相互隔离开,并且可以动态的添加.删除事件. 下面通过实例,一步一步构建一个具体的Javasc ...

  8. YYModel 源码解读(二)之NSObject+YYModel.h (1)

    本篇文章主要介绍 _YYModelPropertyMeta 前边的内容 首先先解释一下前边的辅助函数和枚举变量,在写一个功能的时候,这些辅助的东西可能不是一开始就能想出来的,应该是在后续的编码过程中 ...

  9. Oracle使用SQL传输表空间

    源环境:RHEL 6.4 + Oracle 11.2.0.4 目的环境:RHEL 6.4 + Oracle 11.2.0.4 DG双机 要求:使用SQL传输表空间DBS_D_JINGYU从源环境到目的 ...

  10. 举个栗子学习JavaScript设计模式

    目录 前言 创建型模式 单例模式 构造器+原型 简单工厂模式 工厂模式 创建型模式比较 结构性模式 模块模式 外观模式 混入模式 装饰模式 适配模式 行为型模式 观察者模式 中介者模式 命令模式 责任 ...