公司开发某种中间件产品,该产品的主要功能是从上位系统采集数据,并将采集到的数据做某种处理,然后下发到下级系统中。要求该产品要支持不同类型,不同数量,不同数据格式的上位系统,下发时统一发送符合某种规则或格式的数据流。此外,在增加或删除对某一上位模块支持的时候,无需从新编译该中间件产品。本文讨论不同类型,不同数量,不同数据格式的上位系统,在不需重新编译的情况下,动态添加与删除的技术。

一.模块动态加载技术概述

该技术由配置文件和一组设计模式组成,以配置文件为核心,根据配置文件提供的模块信息,通过反射技术实现了增加和删除新模块而无需重新编译系统的功能。

二.动态加载模块部分的配置文件格式及注释

<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);
                
                
    }