• [ZT].Net中動態建立和調用WebServices的方法


     
       通常我們在程序中需要調用WebService時,都是通過「添加Web引用」,讓VS.NET環境來為我們生成服務代理,然後調用對應的Web服務。這樣是使工作簡單了,但是卻和提供Web服務的URL、方法名、參數綁定在一起了,這是VS.NET自動為我們生成Web服務代理的限制。如果哪一天發佈Web服務的URL改變了,則我們需要重新讓VS.NET生成代理,並重新編譯。在某些情況下,這可能是不能忍受的,我們需要動態調用WebService的能力。比如我們可以把Web服務的URL保存在配置文件中,這樣,當服務URL改變時,只需要修改配置文件就可以了。
         說了這麼多,實際上我們要實現這樣的功能:
    public static object InvokeWebService(string url,  string methodname, object[] args)
         其中,url是Web服務的地址,methodname是要調用服務方法名,args是要調用Web服務所需的參數,返回值就是web服務返回的結果了。

         要實現這樣的功能,你需要這幾個方面的技能:反射、CodeDom、編程使用C#編譯器、WebService。在瞭解這些知識後,就可以容易的實現web服務的動態調用了:
             #region InvokeWebService
            
    //動態調用web服務
            public static object InvokeWebService(string url, string methodname, object[] args)
             {
                
    return WebServiceHelper.InvokeWebService(url ,null ,methodname ,args) ;
             }

            
    public static object InvokeWebService(string url,  string classname, string methodname, object[] args)
             {
                
    string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling" ;
                
    if((classname == null) ||(classname == ""))
                 {
                     classname
    = WebServiceHelper.GetWsClassName(url) ;
                 }

                
    try
                 {
                    
    //獲取WSDL
                     WebClient wc                   = new WebClient();
                     Stream stream                  
    = wc.OpenRead(url+"?WSDL");
                     ServiceDescription sd          
    = ServiceDescription.Read(stream);
                     ServiceDescriptionImporter sdi
    = new ServiceDescriptionImporter();
                     sdi.AddServiceDescription(sd,
    "","");
                     CodeNamespace cn                
    = new CodeNamespace(@namespace);
                    
                    
    //生成客戶端代理類代碼
                     CodeCompileUnit ccu             = new CodeCompileUnit();
                     ccu.Namespaces.Add(cn);
                     sdi.Import(cn ,ccu);
                     CSharpCodeProvider csc          
    = new CSharpCodeProvider();
                     ICodeCompiler icc               
    = csc.CreateCompiler();
                    
                    
    //設定編譯參數
                     CompilerParameters cplist       = new CompilerParameters();
                     cplist.GenerateExecutable       
    = false;
                     cplist.GenerateInMemory         
    = true;
                     cplist.ReferencedAssemblies.Add(
    "System.dll");
                     cplist.ReferencedAssemblies.Add(
    "System.XML.dll");
                     cplist.ReferencedAssemblies.Add(
    "System.Web.Services.dll");
                     cplist.ReferencedAssemblies.Add(
    "System.Data.dll");

                    
    //編譯代理類
                     CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
                    
    if(true == cr.Errors.HasErrors)
                     {
                         System.Text.StringBuilder sb
    = new System.Text.StringBuilder();
                        
    foreach(System.CodeDom.Compiler.CompilerError ce in cr.Errors)
                         {
                             sb.Append(ce.ToString());
                             sb.Append(System.Environment.NewLine);
                         }
                        
    throw new Exception(sb.ToString());
                     }

                    
    //生成代理實例,並調用方法
                     System.Reflection.Assembly assembly = cr.CompiledAssembly;
                     Type t
    = assembly.GetType(@namespace+"."+classname,true,true);
                    
    object obj = Activator.CreateInstance(t);
                     System.Reflection.MethodInfo mi
    = t.GetMethod(methodname);

                    
    return mi.Invoke(obj,args);
                 }
                
    catch(Exception ex)
                 {
                    
    throw new Exception(ex.InnerException.Message,new Exception(ex.InnerException.StackTrace));
                 }
             }

            
    private static string GetWsClassName(string wsUrl)
             {
                
    string[] parts = wsUrl.Split('/') ;
                
    string[] pps   = parts[parts.Length-1].Split('.') ;

                
    return pps[0] ;
             }
            
    #endregion

         上面的註釋已經很好的說明了各代碼段的功能,下面給個例子看看,這個例子是通過訪問http://www.webservicex.net/globalweather.asmx 服務來獲取各大城市的天氣狀況。
                 string url = "http://www.webservicex.net/globalweather.asmx" ;
                
    string[] args = new string[2] ;
                 args[
    0] = this.textBox_CityName.Text ;
                 args[
    1] = "China" ;
                
    object result = WebServiceHelper.InvokeWebService(url ,"GetWeather" ,args) ;
                
    this.label_Result.Text = result.ToString() ;

         上述的例子中,調用web服務使用了兩個參數,第一個是城市的名字,第二個是國家的名字,Web服務返回的是XML文檔,可以從其中解析出溫度、風力等天氣情況。
        
         最後說一下,C#雖然仍屬於靜態語言之列,但是其動態能力也是很強大的,不信,你可以看看Spring.net的AOP實現,這種「無侵入」的AOP實現比通常的.NET聲明式AOP實現(一般是通過AOP Attribute)要漂亮的多。

    完整類的代碼:
      1 //-----代码开始
      2 
      3 using System;
      4 
      5 using System.IO;
      6 
      7 using System.Configuration;
      8 
      9 using System.CodeDom;
     10 
     11 using System.CodeDom.Compiler;
     12 
     13 using System.Net;
     14 
     15 using System.Web.Services;
     16 
     17 using System.Web.Services.Description;
     18 
     19 using Microsoft.CSharp;
     20 
     21 using System.Collections;
     22 
     23 using System.Reflection;
     24 
     25  
     26 
     27 namespace WHelper 
     28 
     29 {
     30 
     31      /// <summary>
     32 
     33      /// WebServiceHelper 的摘要说明。
     34 
     35      /// </summary>
     36 
     37      public class WebServiceHelper
     38 
     39      {
     40 
     41          private string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling" ;        //命名空间
     42 
     43          private Assembly assembly = null;    //程序集;
     44 
     45          private string classname = string.Empty;  //类名称;
     46 
     47          private Type t;             //表示类型;
     48 
     49          private object obj = null;       //表示实例;
     50 
     51          private Boolean isSuccess = false;   //是否创建实例成功;
     52 
     53  
     54 
     55  
     56 
     57          public WebServiceHelper(string Url,string classname)
     58 
     59          {
     60 
     61               if(classname == null || classname == string.Empty)
     62 
     63                    this.classname = GetWsClassName(Url);
     64 
     65               else
     66 
     67                    this.classname = classname;
     68 
     69  
     70 
     71               try
     72 
     73               {
     74 
     75                    //获取WSDL
     76 
     77                    WebClient wc                   = new WebClient();
     78 
     79                    Stream stream                  = wc.OpenRead(Url+"?WSDL");
     80 
     81                    ServiceDescription sd          = ServiceDescription.Read(stream);
     82 
     83                    ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
     84 
     85                    sdi.AddServiceDescription(sd,"","");
     86 
     87                    CodeNamespace cn                = new CodeNamespace(@namespace);
     88 
     89                    stream.Close();
     90 
     91  
     92 
     93                    //生成客户端代理类代码
     94 
     95                    CodeCompileUnit ccu             = new CodeCompileUnit();
     96 
     97                    ccu.Namespaces.Add(cn);
     98 
     99                    sdi.Import(cn ,ccu); 
    100 
    101                    CSharpCodeProvider csc          = new CSharpCodeProvider();
    102 
    103                    ICodeCompiler icc               = csc.CreateCompiler();
    104 
    105                 
    106 
    107                    //设定编译参数
    108 
    109                    CompilerParameters cplist       = new CompilerParameters();
    110 
    111                    cplist.GenerateExecutable       = false;
    112 
    113                    cplist.GenerateInMemory         = true;
    114 
    115                    cplist.ReferencedAssemblies.Add("System.dll");
    116 
    117                    cplist.ReferencedAssemblies.Add("System.XML.dll");
    118 
    119                    cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
    120 
    121                    cplist.ReferencedAssemblies.Add("System.Data.dll");
    122 
    123  
    124 
    125                    //编译代理类
    126 
    127                    CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
    128 
    129                    
    130 
    131                    if(true == cr.Errors.HasErrors)
    132 
    133                    {
    134 
    135                        System.Text.StringBuilder sb = new System.Text.StringBuilder();
    136 
    137                        foreach(System.CodeDom.Compiler.CompilerError ce in cr.Errors)
    138 
    139                        {
    140 
    141                             sb.Append(ce.ToString());
    142 
    143                             sb.Append(System.Environment.NewLine);
    144 
    145                        }
    146 
    147                        throw new Exception(sb.ToString());
    148 
    149                    }                          
    150 
    151    
    152 
    153                    assembly = cr.CompiledAssembly;
    154 
    155               }
    156 
    157               catch (System.Exception ex)
    158 
    159               {
    160 
    161                    throw new Exception(ex.InnerException.Message,new Exception(ex.InnerException.StackTrace));
    162 
    163               }
    164 
    165          }
    166 
    167  
    168 
    169          private Boolean CreateInstance()
    170 
    171          {
    172 
    173               try
    174 
    175               {
    176 
    177                    t = assembly.GetType(@namespace+"."+classname,true,true);
    178 
    179                    obj = Activator.CreateInstance(t);
    180 
    181                    isSuccess = true;
    182 
    183               }
    184 
    185               catch (System.Exception e)
    186 
    187               {
    188 
    189                    throw new Exception(e.Message);
    190 
    191               }
    192 
    193               return isSuccess;
    194 
    195          }
    196 
    197  
    198 
    199          public object InvokeWebService(string methodanme,object[] parms)
    200 
    201          {
    202 
    203  
    204 
    205               if(!isSuccess)
    206 
    207               {
    208 
    209                    CreateInstance();
    210 
    211               }
    212 
    213  
    214 
    215               try
    216 
    217               {             
    218 
    219                    System.Reflection.MethodInfo mi = t.GetMethod(methodanme);
    220 
    221  
    222 
    223                    return mi.Invoke(obj,parms);
    224 
    225             
    226 
    227               }
    228 
    229               catch (System.Exception ex)
    230 
    231               {
    232 
    233                    throw new Exception(ex.InnerException.Message,new Exception(ex.InnerException.StackTrace));
    234 
    235               }
    236 
    237  
    238 
    239          }
    240 
    241  
    242 
    243          private string GetWsClassName(string wsUrl)
    244 
    245          {
    246 
    247               string[] parts = wsUrl.Split('/') ;
    248 
    249               string[] pps   = parts[parts.Length-1].Split('.') ;
    250 
    251  
    252 
    253               return pps[0] ;
    254 
    255          }
    256 
    257      }
    258 
    259 }
    260 
    261  
    262 
    263 //---代码结束
    264 
  • 相关阅读:
    复习重温(类型转换)
    题解SDOI/SXOI2022 子串统计
    frp
    mysql 查询n天内的数据 涂涂
    mysql导入导出数据 涂涂
    查看端口占用+机器联通 涂涂
    java运行服务卡住排查——jstack 涂涂
    mysql链接错误,导致拒绝链接 涂涂
    linux后台执行程序 涂涂
    linux删除指定日期的文件(手动+自动) 涂涂
  • 原文地址:https://www.cnblogs.com/godwar/p/1298502.html
Copyright © 2020-2023  润新知