公司开发某种中间件产品,该产品的主要功能是从上位系统采集数据,并将采集到的数据做某种处理,然后下发到下级系统中。要求该产品要支持不同类型,不同数量,不同数据格式的上位系统,下发时统一发送符合某种规则或格式的数据流。此外,在增加或删除对某一上位模块支持的时候,无需从新编译该中间件产品。本文讨论不同类型,不同数量,不同数据格式的上位系统,在不需重新编译的情况下,动态添加与删除的技术。
一.模块动态加载技术概述
该技术由配置文件和一组设计模式组成,以配置文件为核心,根据配置文件提供的模块信息,通过反射技术实现了增加和删除新模块而无需重新编译系统的功能。
二.动态加载模块部分的配置文件格式及注释
<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接口
1. /// <summary>
2. /// 具体实现模块对象的接口
3. /// </summary>
4. public interface IModule
5. {
6. /// <summary>
7. /// 从WMS上取任务单列表,
8. /// 无论任务单格式是什么都
9. /// 转换成数据集的形式返回。
10. /// </summary>
11. /// <returns></returns>
12. System.Data.DataSet GetDataFromWMS();
13. /// <summary>
14. /// 发送数据到WMS上
15. /// </summary>
16. /// <param name="dsData">数据流集合</param>
17. void SendDataToWMS(System.Data.DataSet dsData);
18. /// <summary>
19. /// 将任务单数据解析成DataSet表集合
20. /// </summary>
21. /// <param name="strData">数据流</param>
22. /// <returns>解析后的表集合</returns>
23. System.Data.DataSet Analysis(string strData);
24.
25. }
26.
1.2 ISystemProxy接口
1. /// <summary>
2. /// WMS访问代理接口
3. /// 所有WMS访问代理对象
4. /// 均需要实现该接口
5. /// </summary>
6. public interface ISystemProxy
7. {
8. /// <summary>
9. /// 注册对象具体WMS访问模块对象
10. /// </summary>
11. /// <param name="Proxy">具体的WMS访问者</param>
12. void Regisiter(WmsProxy.WmsModule.IWMSModule Proxy);
13. /// <summary>
14. /// 获取任务列表
15. /// </summary>
16. /// <param name=’strId’>模块ID</param>
17. /// <returns>返回一个表集合</returns>
18. System.Data.DataSet GetTaskList(string strId);
19. }
1. 对象
2.1 ContreteWMSModule对象
1. /// <summary>
2. /// 上位系统模块具体的访问者
3. /// </summary>
4. public class ContreteWMSModule:IModule
5. {
6.
7. protected DCS_Configuration.Struct.TagWmsModule stModule = null; //配置文件中解析的配置项对象
8.
9. #region 接口
10.
11. public virtual System.Data.DataSet GetDataFromWMS()
12. {
13. //调用反射方法
14. System.Data.DataSet ds = (System.Data.DataSet)methodGetDataFromWMS.Invoke(objClass, new object[0]); //取数据,并保存为字符串
15.
16. //返回数据集
17. return ds;
18. }
19.
20. public virtual void SendDataToWMS(System.Data.DataSet ds) { }
21.
22. #endregion
23. #region 构造器
28. /// <summary>
29. /// 构造器
30. /// </summary>
31. /// <param name="stModule">具体访问者对应的配置信息</param>
32. public ContreteWMSModule(DCS_Configuration.Struct.TagWmsModule stModule)
33. {
34. this.stModule = stModule;
35.
36. InitReflection(); //初始化反射信息
37. }
38. #endregion
39 #region 反射构建对象
45. protected object objClass = null; //类对象
46. protected Type type = null; //对象类型
47. protected System.Reflection.MethodInfo methodGetDataFromWMS = null; //反射方法
48. protected System.Reflection.MethodInfo methodSendDataToWMS = null; //反射方法
49. protected System.Reflection.MethodInfo methodAnalysis = null; //反射方法
50.
51.
52. /// <summary>
53. /// 初始化反射信息
54. /// </summary>
55. protected void InitReflection()
56. {
57. System.Reflection.Assembly assembly =
58. System.Reflection.Assembly.LoadFrom(stModule.Path);
59.
60. //反射出对象
61. objClass = assembly.CreateInstance(stModule.AssemblyName + "." + stModule.ClassName);
62.
63. //反射除类型
64. type = objClass.GetType();
65.
66. //反射出方法
67. methodGetDataFromWMS = type.GetMethod("GetTask");
68. methodSendDataToWMS = type.GetMethod("SendTask");
69. methodAnalysis = type.GetMethod("Analysis");
70.
71. }
72. #endregion
73.
75. }
76.
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 //遍历所有对象
{
if //找到该对象
{
return visitor;
}
}
//未找到ID对应的注册对象
DCSException.UnknowException err =
new DCSException.UnknowException("未找到ID对应的注册对象", "GetVisitorByID", DCSException.ErrCode.ERR_NOT_FIND_OBJECT_WITH_ID);
throw (err);
}