考察如下应用:
公司开发某种中间件产品,该产品的主要功能是从上位系统采集数据,并将采集到的数据做某种处理,然后下发到下级系统中。要求该产品要支持不同类型,不同数量,不同数据格式的上位系统,下发时统一发送符合某种规则或格式的数据流。此外,在增加或删除对某一上位模块支持的时候,无需从新编译该中间件产品。本文讨论不同类型,不同数量,不同数据格式的上位系统,在不需重新编译的情况下,动态添加与删除的技术。
一.模块动态加载技术概述
该技术由配置文件和一组设计模式组成,以配置文件为核心,根据配置文件提供的模块信息,通过反射技术实现了增加和删除新模块而无需重新编译系统的功能。
二.动态加载模块部分的配置文件格式及注释
<WMS_MODULE>
<WMS>
<ID>1</ID> <!--模块编号-->
<PATH>C:\ContreteWMS1.dll</PATH> <!--具体的WMS引擎模块位置-->
<ASSEMBLYNAME>ContreteWMS1</ASSEMBLYNAME> <!--程序集名-->
<CLASSNAME>ContreteWMS1</CLASSNAME> <!--类名-->
<WMS_METHOD> <!--支持的方法列表-->
<ID>1</ID> <!--所属WMS模块编号,同“模块编号”-->
<METHOD>GetTask</METHOD> <!--其中一个方法-->
<INPUT_PARAMETER>NONE</INPUT_PARAMETER> <!--输入参数类型,NONE为无输入-->
<RETURN_PARAMETER>System.Data.DataSet</RETURN_PARAMETER> <!--返回类型-->
</WMS_METHOD>
<WMS_METHOD>
<ID>1</ID>
<METHOD>SendTask</METHOD>
<INPUT_PARAMETER>System.Data.DataSet</INPUT_PARAMETER>
<RETURN_PARAMETER>NONE</RETURN_PARAMETER>
</WMS_METHOD>
</WMS>
<WMS>
<ID>2</ID>
<PATH>C:\ContreteDemoWMS2.dll</PATH>
<ASSEMBLYNAME>ContreteDemoWMS2</ASSEMBLYNAME>
<CLASSNAME>ContreteDemoWMS2</CLASSNAME>
<WMS_METHOD>
<ID>2</ID>
<METHOD>GetTask</METHOD>
<INPUT_PARAMETER>NONE</INPUT_PARAMETER>
<RETURN_PARAMETER>System.Data.DataSet</RETURN_PARAMETER>
</WMS_METHOD>
<WMS_METHOD>
<ID>2</ID>
<METHOD>SendTask</METHOD>
<INPUT_PARAMETER>System.Data.DataSet</INPUT_PARAMETER>
<RETURN_PARAMETER>NONE</RETURN_PARAMETER>
</WMS_METHOD>
</WMS>
</WMS_MODULE>
三.动态加载模块部分的类图
数据类型:
◎DataSet:数据集
◎List<IModule>:IMoudle对象的列表
接口:
◎ISystemProxy:代理对象的接口
◎IModule:具体实现对象的接口
对象:
◎XmlConfiguration:配置文件对象,加载配置文件信息
◎WMSProxy:上位系统(WMS)接口模块的访问代理对象
◎MISProxy:上位系统(MIS)系统接口模块的访问代理对象
◎ContreteWMSModule:上位系统(WMS)模块的具体访问者
◎WMSModule1-N:与上位系统(WMS)接口的具体实现
四.动态加载模块技术的核心代码
1. 接口部分
1.1 IModule接口
- /// <summary>
- /// 具体实现模块对象的接口
- /// </summary>
- public interface IModule
- {
- /// <summary>
- /// 从WMS上取任务单列表,
- /// 无论任务单格式是什么都
- /// 转换成数据集的形式返回。
- /// </summary>
- /// <returns></returns>
- System.Data.DataSet GetDataFromWMS();
- /// <summary>
- /// 发送数据到WMS上
- /// </summary>
- /// <param name="dsData">数据流集合</param>
- void SendDataToWMS(System.Data.DataSet dsData);
- /// <summary>
- /// 将任务单数据解析成DataSet表集合
- /// </summary>
- /// <param name="strData">数据流</param>
- /// <returns>解析后的表集合</returns>
- System.Data.DataSet Analysis(string strData);
- }
1.2 ISystemProxy接口
- /// <summary>
- /// WMS访问代理接口
- /// 所有WMS访问代理对象
- /// 均需要实现该接口
- /// </summary>
- public interface ISystemProxy
- {
- /// <summary>
- /// 注册对象具体WMS访问模块对象
- /// </summary>
- /// <param name="Proxy">具体的WMS访问者</param>
- void Regisiter(WmsProxy.WmsModule.IWMSModule Proxy);
- /// <summary>
- /// 获取任务列表
- /// </summary>
- /// <param name=’strId’>模块ID</param>
- /// <returns>返回一个表集合</returns>
- System.Data.DataSet GetTaskList(string strId);
- }
1. 对象
2.1 ContreteWMSModule对象
- /// <summary>
- /// 上位系统模块具体的访问者
- /// </summary>
- public class ContreteWMSModule:IModule
- {
- protected DCS_Configuration.Struct.TagWmsModule stModule = null; //配置文件中解析的配置项对象
- #region 接口
- public virtual System.Data.DataSet GetDataFromWMS()
- {
- //调用反射方法
- System.Data.DataSet ds = (System.Data.DataSet)methodGetDataFromWMS.Invoke(objClass, new object[0]); //取数据,并保存为字符串
- //返回数据集
- return ds;
- }
- public virtual void SendDataToWMS(System.Data.DataSet ds) { }
- #endregion
- #region 构造器
- /// <summary>
- /// 构造器
- /// </summary>
- /// <param name="stModule">具体访问者对应的配置信息</param>
- public ContreteWMSModule(DCS_Configuration.Struct.TagWmsModule stModule)
- {
- this.stModule = stModule;
- InitReflection(); //初始化反射信息
- }
- #endregion
- #region 反射构建对象
- protected object objClass = null; //类对象
- protected Type type = null; //对象类型
- protected System.Reflection.MethodInfo methodGetDataFromWMS = null; //反射方法
- protected System.Reflection.MethodInfo methodSendDataToWMS = null; //反射方法
- protected System.Reflection.MethodInfo methodAnalysis = null; //反射方法
- /// <summary>
- /// 初始化反射信息
- /// </summary>
- protected void InitReflection()
- {
- System.Reflection.Assembly assembly =
- System.Reflection.Assembly.LoadFrom(stModule.Path);
- //反射出对象
- objClass = assembly.CreateInstance(stModule.AssemblyName + "." + stModule.ClassName);
- //反射除类型
- type = objClass.GetType();
- //反射出方法
- methodGetDataFromWMS = type.GetMethod("GetTask");
- methodSendDataToWMS = type.GetMethod("SendTask");
- methodAnalysis = type.GetMethod("Analysis");
- }
- #endregion
- }
2.2 WMSProxy
/// <summary>
/// 具体代理类
/// </summary>
public class WMSProxy:ISystemProxy
{
private List<WmsProxy.WmsModule.IWMSModule> visitors = new List<WmsProxy.WmsModule.IWMSModule>(); //具体访问者列表
#region 接口
/// <summary>
/// 获取已经注册的模块
/// </summary>
public List<WmsProxy.WmsModule.IWMSModule> RegisitedModules
{
get { return visitors; }
}
/// <summary>
/// 注册访问模块列表
/// </summary>
/// <param name="visitor">具体WMS访问模块</param>
public void Regisiter(WmsProxy.WmsModule.IWMSModule visitor)
{
visitors.Add(visitor);
return;
}
/// <summary>
/// 获取任务列表
/// </summary>
/// <param name="strID">WMS访问模块对应的ID</param>
/// <returns></returns>
public System.Data.DataSet GetTaskList(string strID)
{
System.Data.DataSet ds = new System.Data.DataSet();
WmsProxy.WmsModule.ContreteModule visitor = GetVisitorByID(strID);
ds=visitor.GetDataFromWMS();
return ds;
}
/// <summary>
/// 根据ID查找对应模块
/// </summary>
/// <param name="strID"></param>
/// <returns></returns>
private WmsProxy.WmsModule.ContreteModule GetVisitorByID(string strID)
{
foreach (WmsModule.ContreteModule visitor in visitors) //遍历所有对象
{
if (visitor.Id.CompareTo(strID) == 0) //找到该对象
{
return visitor;
}
}
//未找到ID对应的注册对象
DCSException.UnknowException err =
new DCSException.UnknowException("未找到ID对应的注册对象", "GetVisitorByID", DCSException.ErrCode.ERR_NOT_FIND_OBJECT_WITH_ID);
throw (err);
}
QQ:819543772
EMail:wuchunlei@163.com