zoukankan      html  css  js  c++  java
  • 【转载】客户端插件IPassiveAddin

    ESFramework介绍之(8)-- 客户端插件IPassiveAddin

        前文已经提到了,在IServerAgent的基础上,客户端也可以采用插件的结构形式,客户端插件需要实现IPassiveAddin接口。
        我的想法是,当客户端主程序加载一个新的PassiveAddin时,可以在某个菜单的子Items上添加一项,当双击这个子菜单项时,则弹出该客户端插件提供的“业务操作窗体”。这只是使用客户端插件的可行方式之一,你完全可以根据你的应用来决定使用形式。IPassiveAddin接口定义如下:

     1     /// <summary>
     2     /// IPassiveAddin 用于客户端的插件。通常一个PassiveAddin对应着一个服务端的功能插件FunAddin
     3     /// zhuweisky 2006.03.13
     4     /// </summary>
     5     public interface IPassiveAddin : IAddin
     6     {
     7         Type AddinFormType{get ;} //AddinFormType必须实现IAddinForm接口
     8     }
     9 
    10     public interface IPassiveAddinForm
    11     {
    12         //PassiveAddin通过IServerAgent发送请求并获取结果
    13         void Initialize(IServerAgent serverAgent ,string userID) ;
    14     }

        IPassiveAddin直接从IAddin继承,仅仅增加了一个属性AddinFormType,这个属性就是前面说的客户端插件提供的“业务操作窗体”。“业务操作窗体”必须从IPassiveAddinForm接口继承。
        “业务操作窗体”只有通过暴露的Initialize方法获取IServerAgent引用后,才能发送请求获取结果。Initialize方法的第二个参数说明当前时哪个用户在操作,这样客户端插件在构建请求消息时,需要将userID填充到请求消息的消息头中去,这样服务器才会知道这个消息的来源。

        下面的代码说明了客户端主程序是如何加载IPassiveAddin的:

     1          private void LoadPassiveAddins()
     2         {
     3             this.lIToolStripMenuItem_addin.DropDownItems.Clear();
     4 
     5             string directory = System.IO.Directory.GetParent(System.Windows.Forms.Application.ExecutablePath).FullName;
     6             this.addinManagement.LoadAllAddins(directory, true);
     7 
     8             foreach (IAddin addin in this.addinManagement.AddinList)
     9             {
    10                 IPassiveAddin passiveAddin = addin as IPassiveAddin;
    11                 if (passiveAddin != null)
    12                 {
    13                     ToolStripItem item = new ToolStripMenuItem(passiveAddin.ServiceName, nullnew EventHandler(this.OnAddinMenuClicked));
    14                     item.Tag = passiveAddin;
    15                     this.lIToolStripMenuItem_addin.DropDownItems.Add(item);
    16                 }
    17             }
    18         }
    19 
    20         private void OnAddinMenuClicked(object sender, EventArgs e)
    21         {
    22             try
    23             {
    24                 ToolStripItem item = (ToolStripItem)sender;
    25                 IPassiveAddin passiveAddin = (IPassiveAddin)item.Tag;
    26                 Form addinForm = (Form)Activator.CreateInstance(passiveAddin.AddinFormType);
    27                 ((IPassiveAddinForm)addinForm).Initialize(this.tcpServerAgent ,this.currentUserID);
    28                 addinForm.Show();
    29             }
    30             catch (Exception ee)
    31             {
    32                 ee = ee;
    33             }
    34         }

        上述的介绍没有什么难点,仔细体会一下都能明白,就不多说了。这里我给出一个测试用的功能插件和对应的客户端插件示例。示例的功能插件用于从http://www.webservicex.net/globalweather.asmx 通过WebService获取城市的天气信息,而客户端插件则用于为用户提供这项服务。

    先看服务端功能插件实现:

    WeatherPreAddin
      1 public class WeatherPreAddin :IFunAddin
      2     {
      3         private IContractHelper contractHelper = new ContractHelper() ;
      4
      5         public WeatherPreAddin()
      6         {
      7            
      8         }
      9
     10         #region IAddin 成员
     11
     12         public string ServiceName
     13         {
     14             get
     15             {
     16                 // TODO:  添加 WeatherPreAddin.ServiceName getter 实现
     17                 return "天气预测服务";
     18             }
     19         }
     20
     21         public void OnLoading()
     22         {
     23             // TODO:  添加 WeatherPreAddin.OnLoading 实现
     24         }
     25
     26         public string CatalogName
     27         {
     28             get
     29             {
     30                 // TODO:  添加 WeatherPreAddin.CatalogName getter 实现
     31                 return "";
     32             }
     33         }
     34
     35         public int ServiceKey
     36         {
     37             get
     38             {
     39                 // TODO:  添加 WeatherPreAddin.ServiceKey getter 实现
     40                 return 987 ;
     41             }
     42         }
     43
     44         public string Description
     45         {
     46             get
     47             {
     48                 // TODO:  添加 WeatherPreAddin.Description getter 实现
     49                 return "";
     50             }
     51         }
     52
     53         public void BeforeTerminating()
     54         {
     55             // TODO:  添加 WeatherPreAddin.BeforeTerminating 实现
     56         }
     57
     58         public bool Enabled
     59         {
     60             get
     61             {
     62                 // TODO:  添加 WeatherPreAddin.Enabled getter 实现
     63                 return true;
     64             }
     65             set
     66             {
     67                 // TODO:  添加 WeatherPreAddin.Enabled setter 实现
     68             }
     69         }
     70
     71         public float Version
     72         {
     73             get
     74             {
     75                 // TODO:  添加 WeatherPreAddin.Version getter 实现
     76                 return 1;
     77             }
     78         }
     79
     80         public string AddinType
     81         {
     82             get
     83             {
     84                 // TODO:  添加 WeatherPreAddin.AddinType getter 实现
     85                 return null;
     86             }
     87         }
     88
     89         public AddinAppendixInfo AddinAppendixInfo
     90         {
     91             get
     92             {
     93                 // TODO:  添加 WeatherPreAddin.AddinAppendixInfo getter 实现
     94                 return null;
     95             }
     96         }
     97
     98         #endregion
     99
    100         #region IDataDealer 成员
    101
    102         public ESFramework.Network.NetMessage DealRequestMessage(ESFramework.Network.NetMessage reqMsg)
    103         {   
    104            
    105             try
    106             {
    107                 string url = "http://www.webservicex.net/globalweather.asmx" ;
    108                 string[] args = new string[2] ;
    109                 args[0] = this.contractHelper.GetStrFromStream(reqMsg.Body ,reqMsg.BodyOffset ,reqMsg.Header.MessageBodyLength) ;
    110                 args[1] = "China" ;
    111                 object result = WebServiceHelper.InvokeWebService(url ,"GetWeather" ,args) ;
    112            
    113                 XmlParser parser = new XmlParser(result.ToString() ,null) ;
    114                 WeatherPredictionContract body = new WeatherPredictionContract(this.contractHelper) ;
    115                 body.Pressure = parser.GetSingleLayerConfigValue("Pressure") ;
    116                 body.PressureLen = this.contractHelper.GetBytesFromStr(body.Pressure).Length ;
    117
    118                 body.PreTime  = parser.GetSingleLayerConfigValue("Time") ;
    119                 body.PreTimeLen = this.contractHelper.GetBytesFromStr(body.PreTime).Length ;
    120
    121                 body.Temprature = parser.GetSingleLayerConfigValue("Temperature") ;
    122                 body.TempratureLen = this.contractHelper.GetBytesFromStr(body.Temprature).Length ;
    123
    124                 body.Visbility  = parser.GetSingleLayerConfigValue("Visibility") ;
    125                 body.VisbilityLen = this.contractHelper.GetBytesFromStr(body.Visbility).Length ;
    126
    127                 body.Wind  = parser.GetSingleLayerConfigValue("Wind") ;
    128                 body.WindLen = this.contractHelper.GetBytesFromStr(body.Wind).Length ;
    129
    130                 reqMsg.Header.MessageBodyLength = body.GetStreamLength() ;
    131
    132                 return new NetMessage(reqMsg.Header ,body.ToStream() ,0) ;
    133
    134             }
    135             catch(Exception ee)
    136             {
    137                 ee = ee ;
    138                 reqMsg.Header.MessageBodyLength = 0 ;
    139                 reqMsg.Header.Result = ServiceResultType.FailureByOtherCause ;
    140                 return new NetMessage(reqMsg.Header ,null);
    141             }
    142         }
    143
    144         #endregion
    145     }

    主要是DealRequestMessage方法的实现,代码非常简单,通过WebService获取指定城市的天气情况,将返回的XML解析封装成IContract,然后返回给客户端。

    接下来看客户端插件的实现,分为两步:首先是“业务操作窗体”界面设计

     该窗体要从IPassiveAddinForm接口继承。当点击按钮时,处理代码为:

    button1_Click
            private void button1_Click(object sender, System.EventArgs e)
            {
                string cityName = ESFramework.Common.ChsToSpellConverter.Convert(this.comboBox1.SelectedItem.ToString()) ;
                WeatherReqContract body = new WeatherReqContract(this.contractHelper) ;
                body.cityName = cityName ;
                MessageHeader header = new MessageHeader(this.contractHelper) ;
                header.TypeKey = int.Parse(this.textBox_asCityCode.Text.Trim()) ;
                header.ServiceKey = 987 ;
                header.UserID     = this.curUserID ;
                header.UserIDLen  = this.contractHelper.GetBytesFromStr(this.curUserID).Length ;
                header.MessageBodyLength = body.GetStreamLength() ;

                ESFramework.Network.Message msg = new ESFramework.Network.Message(header ,body) ;
                NetMessage resMsg = this.theAgent.CommitRequest(msg ,DataPriority.Common ,true) ;
                if(resMsg.Header.Result != ServiceResultType.ServiceSucceed)
                {
                    MessageBox.Show("没有发现对应的服务~!") ;
                    return ;
                }

                WeatherPredictionContract resContract = new WeatherPredictionContract(this.contractHelper) ;
                resContract.FillMyself(resMsg.Body ,resMsg.BodyOffset) ;

                this.groupBox1.Text = "服务结果--" + this.comboBox1.SelectedItem.ToString() ;

                this.label_pressure.Text = resContract.Pressure ;
                this.label_temp.Text     = resContract.Temprature ;
                this.label_vis.Text      = resContract.Visbility ;
                this.label_wind.Text     = resContract.Wind ;
                this.label_time.Text     = resContract.PreTime ;
            }

        注意,theAgent成员即是通过Initialize传入的IServerAgent引用!

    接着是
    IPassiveAddin实现:

    WeatherPassiveAddin
      1     public class WeatherPassiveAddin :IPassiveAddin
      2     {
      3         public WeatherPassiveAddin()
      4         {
      5         }
      6
      7         #region IPassiveAddin 成员
      8
      9         public Type AddinFormType
     10         {
     11             get
     12             {               
     13                 return typeof(AddinForm); //AddinForm即前面实现的业务窗体
     14             }
     15         }
     16
     17         #endregion
     18
     19         #region IAddin 成员
     20
     21         public string ServiceName
     22         {
     23             get
     24             {
     25                 // TODO:  添加 WeatherPassiveAddin.ServiceName getter 实现
     26                 return "天气预测服务";
     27             }
     28         }
     29
     30         public void OnLoading()
     31         {
     32             // TODO:  添加 WeatherPassiveAddin.OnLoading 实现
     33         }
     34
     35         public string CatalogName
     36         {
     37             get
     38             {
     39                 // TODO:  添加 WeatherPassiveAddin.CatalogName getter 实现
     40                 return null;
     41             }
     42         }
     43
     44         public int ServiceKey
     45         {
     46             get
     47             {
     48                 // TODO:  添加 WeatherPassiveAddin.ServiceKey getter 实现
     49                 return 987;
     50             }
     51         }
     52
     53         public string Description
     54         {
     55             get
     56             {
     57                 // TODO:  添加 WeatherPassiveAddin.Description getter 实现
     58                 return null;
     59             }
     60         }
     61
     62         public void BeforeTerminating()
     63         {
     64             // TODO:  添加 WeatherPassiveAddin.BeforeTerminating 实现
     65         }
     66
     67         public bool Enabled
     68         {
     69             get
     70             {
     71                 // TODO:  添加 WeatherPassiveAddin.Enabled getter 实现
     72                 return true;
     73             }
     74             set
     75             {
     76                 // TODO:  添加 WeatherPassiveAddin.Enabled setter 实现
     77             }
     78         }
     79
     80         public float Version
     81         {
     82             get
     83             {
     84                 // TODO:  添加 WeatherPassiveAddin.Version getter 实现
     85                 return 1;
     86             }
     87         }
     88
     89         public string AddinType
     90         {
     91             get
     92             {
     93                 // TODO:  添加 WeatherPassiveAddin.AddinType getter 实现
     94                 return null;
     95             }
     96         }
     97
     98         public AddinAppendixInfo AddinAppendixInfo
     99         {
    100             get
    101             {
    102                 // TODO:  添加 WeatherPassiveAddin.AddinAppendixInfo getter 实现
    103                 return null;
    104             }
    105         }
    106
    107         #endregion
    108     }

        需要格外注意要实现AddinFormType属性,就是前面实现的“业务窗体”类型。 

    下图是功能服务器加载功能插件的截图:

     

    下图是客户端加载客户插件后的截图:

     

    下图是客户端插件提供服务的截图:

     

         经过上述的介绍,读者应该对开发服务端的功能插件和客户端插件有些了解了。快结束的时候,再为下篇blog开个头。当我们开发了客户端插件和服务端插件后,做调试是一项非常麻烦的工作,因为不仅要启动应用服务器,还要启动客户端主程序、功能服务器才行。为了简化这个过程,我实现了一个Bridge应用程序,只需要加载一pair插件(服务端插件和对应的客户插件),即可进行两个插件的调试,而不用在启动客户端、AS、FS了。

  • 相关阅读:
    SpringMVC + MyBatis简单示例
    JSP---JSTL核心标签库的使用
    HBASE安装 (HA)
    HBase 常用Shell命令(转载)
    kafka quick start
    在IDEA中实战Git
    kibana6.2.2安装
    elasticsearch-head插件安装
    elasticsearch6.2.2安装
    jdk1.8安装
  • 原文地址:https://www.cnblogs.com/fx2008/p/2263077.html
Copyright © 2011-2022 走看看