首页 > 代码库 > C# 动态调用WebService

C# 动态调用WebService

原文:C# 动态调用WebService

动态调用webservice,就可以不用添加web引用了,上线的话也只是需要改一下wsdl地址就可以了 

1.动态调用的方法: 

C#代码  收藏代码
  1. /// <summary>  
  2.         ///  动态webservice调用  
  3.         /// </summary>  
  4.         /// <returns>string</returns>    
  5.         public string wsTest()  
  6.         {  
  7.             string url = "http://localhost:8080/myWebserviceTest/services/myServices?wsdl";//wsdl地址  
  8.             string name = "wsTest";//javaWebService开放的接口  
  9.             WebServiceProxy wsd = new WebServiceProxy(url, name);  
  10.   
  11.             string[] str = { "测试c#调用java的webService" , "Hello WebService"};  
  12.   
  13.             string suc = (string)wsd.ExecuteQuery(name, str);  
  14.   
  15.             return suc;  
  16.         }  



2.动态调用具体类: 

C#代码  收藏代码
  1. using System;  
  2. using System.Collections;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Linq;  
  6. using System.Web;  
  7. using System.Web.Services;  
  8. using System.Web.Services.Protocols;  
  9. using System.Xml.Linq;  
  10.   
  11.   
  12. using System.IO;  
  13. using System.Net;  
  14. using System.CodeDom;  
  15. using System.CodeDom.Compiler;  
  16. using System.Web.Services.Description;  
  17. using System.Xml.Serialization;  
  18. using System.Web.Services.Discovery;  
  19. using System.Xml.Schema;  
  20. using System.Text;  
  21. using System.Security.Cryptography;  
  22. using System.Reflection;  
  23. using System.Collections.Generic;  
  24. using System.Xml;  
  25.   
  26. namespace TPSVService  
  27. {  
  28.     /// <summary>  
  29.     /// WebServiceProxy 的摘要说明  
  30.     /// </summary>  
  31.     [WebService(Namespace = "http://tempuri.org/")]  
  32.     [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]  
  33.     [ToolboxItem(false)]  
  34.     // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。  
  35.     // [System.Web.Script.Services.ScriptService]  
  36.     public class WebServiceProxy : System.Web.Services.WebService  
  37.     {  
  38.  
  39.         #region 私有变量和属性定义  
  40.         /// <summary>                   
  41.         /// web服务地址                           
  42.         /// </summary>                              
  43.         private string _wsdlUrl = string.Empty;  
  44.         /// <summary>                   
  45.         /// web服务名称                           
  46.         /// </summary>                              
  47.         private string _wsdlName = string.Empty;  
  48.         /// <summary>                   
  49.         /// 代理类命名空间                           
  50.         /// </summary>                              
  51.         private string _wsdlNamespace = "FrameWork.WebService.DynamicWebServiceCalling.{0}";  
  52.         /// <summary>                   
  53.         /// 代理类类型名称                           
  54.         /// </summary>                              
  55.         private Type _typeName = null;  
  56.         /// <summary>                   
  57.         /// 程序集名称                             
  58.         /// </summary>                              
  59.         private string _assName = string.Empty;  
  60.         /// <summary>                   
  61.         /// 代理类所在程序集路径                            
  62.         /// </summary>                              
  63.         private string _assPath = string.Empty;  
  64.         /// <summary>                   
  65.         /// 代理类的实例                            
  66.         /// </summary>                              
  67.         private object _instance = null;  
  68.         /// <summary>                   
  69.         /// 代理类的实例                            
  70.         /// </summary>                              
  71.         private object Instance  
  72.         {  
  73.             get  
  74.             {  
  75.                 if (_instance == null)  
  76.                 {  
  77.                     _instance = Activator.CreateInstance(_typeName);  
  78.                     return _instance;  
  79.                 }  
  80.                 else  
  81.                     return _instance;  
  82.             }  
  83.         }  
  84.         #endregion  
  85.  
  86.         #region 构造函数  
  87.         public WebServiceProxy(string wsdlUrl)  
  88.         {  
  89.   
  90.             this._wsdlUrl = wsdlUrl;  
  91.             string wsdlName = WebServiceProxy.getWsclassName(wsdlUrl);  
  92.             this._wsdlName = wsdlName;  
  93.             this._assName = string.Format(_wsdlNamespace, wsdlName);  
  94.             this._assPath = Path.GetTempPath() + this._assName + getMd5Sum(this._wsdlUrl) + ".dll";  
  95.             this.CreateServiceAssembly();  
  96.         }  
  97.   
  98.         public WebServiceProxy(string wsdlUrl, string wsdlName)  
  99.         {  
  100.             this._wsdlUrl = wsdlUrl;  
  101.             this._wsdlName = wsdlName;  
  102.             this._assName = string.Format(_wsdlNamespace, wsdlName);  
  103.             this._assPath = Path.GetTempPath() + this._assName + getMd5Sum(this._wsdlUrl) + ".dll";  
  104.             this.CreateServiceAssembly();  
  105.         }  
  106.         #endregion  
  107.  
  108.         #region 得到WSDL信息,生成本地代理类并编译为DLL,构造函数调用,类生成时加载  
  109.         /// <summary>                           
  110.         /// 得到WSDL信息,生成本地代理类并编译为DLL                           
  111.         /// </summary>                              
  112.         private void CreateServiceAssembly()  
  113.         {  
  114.             if (this.checkCache())  
  115.             {  
  116.                 this.initTypeName();  
  117.                 return;  
  118.             }  
  119.             if (string.IsNullOrEmpty(this._wsdlUrl))  
  120.             {  
  121.                 return;  
  122.             }  
  123.             try  
  124.             {  
  125.                 //使用WebClient下载WSDL信息                         
  126.                 WebClient web = new WebClient();  
  127.                 Stream stream = web.OpenRead(this._wsdlUrl);  
  128.                 ServiceDescription description = ServiceDescription.Read(stream);//创建和格式化WSDL文档  
  129.                 ServiceDescriptionImporter importer = new ServiceDescriptionImporter();//创建客户端代理代理类  
  130.                 importer.ProtocolName = "Soap";  
  131.                 importer.Style = ServiceDescriptionImportStyle.Client;  //生成客户端代理                         
  132.                 importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;  
  133.                 importer.AddServiceDescription(description, null, null);//添加WSDL文档  
  134.                 //使用CodeDom编译客户端代理类                   
  135.                 CodeNamespace nmspace = new CodeNamespace(_assName);    //为代理类添加命名空间                  
  136.                 CodeCompileUnit unit = new CodeCompileUnit();  
  137.                 unit.Namespaces.Add(nmspace);  
  138.                 this.checkForImports(this._wsdlUrl, importer);  
  139.                 ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);  
  140.                 CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");  
  141.                 CompilerParameters parameter = new CompilerParameters();  
  142.                 parameter.ReferencedAssemblies.Add("System.dll");  
  143.                 parameter.ReferencedAssemblies.Add("System.XML.dll");  
  144.                 parameter.ReferencedAssemblies.Add("System.Web.Services.dll");  
  145.                 parameter.ReferencedAssemblies.Add("System.Data.dll");  
  146.                 parameter.GenerateExecutable = false;  
  147.                 parameter.GenerateInMemory = false;  
  148.                 parameter.IncludeDebugInformation = false;  
  149.                 CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);  
  150.                 provider.Dispose();  
  151.                 if (result.Errors.HasErrors)  
  152.                 {  
  153.                     string errors = string.Format(@"编译错误:{0}错误!", result.Errors.Count);  
  154.                     foreach (CompilerError error in result.Errors)  
  155.                     {  
  156.                         errors += error.ErrorText;  
  157.                     }  
  158.                     throw new Exception(errors);  
  159.                 }  
  160.                 this.copyTempAssembly(result.PathToAssembly);  
  161.                 this.initTypeName();  
  162.             }  
  163.             catch (Exception e)  
  164.             {  
  165.                 throw new Exception(e.Message);  
  166.             }  
  167.         }  
  168.         #endregion  
  169.  
  170.         #region 执行Web服务方法  
  171.         /// <summary>                           
  172.         /// 执行代理类指定方法,有返回值                                
  173.         /// </summary>                                  
  174.         /// <param   name="methodName">方法名称</param>                           
  175.         /// <param   name="param">参数</param>                              
  176.         /// <returns>object</returns>                                 
  177.         public object ExecuteQuery(string methodName, object[] param)  
  178.         {  
  179.             object rtnObj = null;   
  180.             string[] args = new string[2];  
  181.             List<string> list = new List<string>();  
  182.             List<string> list1 = new List<string>();  
  183.             List<string> list2 = new List<string>();  
  184.             object[] obj = new object[3];  
  185.   
  186.             try  
  187.             {  
  188.                 if (this._typeName == null)  
  189.                 {  
  190.                     //记录Web服务访问类名错误日志代码位置  
  191.                     throw new TypeLoadException("Web服务访问类名【" + this._wsdlName + "】不正确,请检查!");  
  192.                 }  
  193.                 //调用方法  
  194.                 MethodInfo mi = this._typeName.GetMethod(methodName);  
  195.                 if (mi == null)  
  196.                 {  
  197.                     //记录Web服务方法名错误日志代码位置  
  198.                     throw new TypeLoadException("Web服务访问方法名【" + methodName + "】不正确,请检查!");  
  199.                 }  
  200.                 try  
  201.                 {  
  202.                     if (param == null)  
  203.                         rtnObj = mi.Invoke(Instance, null);  
  204.                     else {  
  205.                         list.Add("Hello ");  
  206.                         list.Add("WebService ");  
  207.                         list.Add(" ! ");  
  208.   
  209.                         list1.Add("I ");  
  210.                         list1.Add("am ");  
  211.                         list1.Add("test ");  
  212.   
  213.                         list2.Add("do ");  
  214.                         list2.Add("it ");  
  215.                         list2.Add("now ");  
  216.   
  217.                         obj[0] = list;  
  218.                         obj[1] = list1;  
  219.                         obj[2] = list2;  
  220.   
  221.                         rtnObj = mi.Invoke(Instance, new object[] { obj });  
  222.                         //rtnObj = mi.Invoke(Instance, new object[] { param });  
  223.                     }  
  224.                 }  
  225.                 catch (TypeLoadException tle)  
  226.                 {  
  227.                     //记录Web服务方法参数个数错误日志代码位置  
  228.                     throw new TypeLoadException("Web服务访问方法【" + methodName + "】参数个数不正确,请检查!", new TypeLoadException(tle.StackTrace));  
  229.                 }  
  230.             }  
  231.             catch (Exception ex)  
  232.             {  
  233.                 throw new Exception(ex.Message, new Exception(ex.StackTrace));  
  234.             }  
  235.             return rtnObj;  
  236.         }  
  237.   
  238.         /// <summary>                           
  239.         /// 执行代理类指定方法,无返回值                                
  240.         /// </summary>                                  
  241.         /// <param   name="methodName">方法名称</param>                           
  242.         /// <param   name="param">参数</param>                              
  243.         public void ExecuteNoQuery(string methodName, object[] param)  
  244.         {  
  245.             try  
  246.             {  
  247.                 if (this._typeName == null)  
  248.                 {  
  249.                     //记录Web服务访问类名错误日志代码位置  
  250.                     throw new TypeLoadException("Web服务访问类名【" + this._wsdlName + "】不正确,请检查!");  
  251.                 }  
  252.                 //调用方法  
  253.                 MethodInfo mi = this._typeName.GetMethod(methodName);  
  254.                 if (mi == null)  
  255.                 {  
  256.                     //记录Web服务方法名错误日志代码位置  
  257.                     throw new TypeLoadException("Web服务访问方法名【" + methodName + "】不正确,请检查!");  
  258.                 }  
  259.                 try  
  260.                 {  
  261.                     if (param == null)  
  262.                         mi.Invoke(Instance, null);  
  263.                     else  
  264.                         mi.Invoke(Instance, param);  
  265.                 }  
  266.                 catch (TypeLoadException tle)  
  267.                 {  
  268.                     //记录Web服务方法参数个数错误日志代码位置  
  269.                     throw new TypeLoadException("Web服务访问方法【" + methodName + "】参数个数不正确,请检查!", new TypeLoadException(tle.StackTrace));  
  270.                 }  
  271.             }  
  272.             catch (Exception ex)  
  273.             {  
  274.                 throw new Exception(ex.Message, new Exception(ex.StackTrace));  
  275.             }  
  276.         }  
  277.         #endregion  
  278.  
  279.         #region 私有方法  
  280.         /// <summary>                               
  281.         /// 得到代理类类型名称                                 
  282.         /// </summary>                                  
  283.         private void initTypeName()  
  284.         {  
  285.             Assembly serviceAsm = Assembly.LoadFrom(this._assPath);  
  286.             Type[] types = serviceAsm.GetTypes();  
  287.             string objTypeName = "";  
  288.             foreach (Type t in types)  
  289.             {  
  290.                 if (t.BaseType == typeof(SoapHttpClientProtocol))  
  291.                 {  
  292.                     objTypeName = t.Name;  
  293.                     break;  
  294.                 }  
  295.             }  
  296.             _typeName = serviceAsm.GetType(this._assName + "." + objTypeName);  
  297.         }  
  298.   
  299.         /// <summary>                       
  300.         /// 根据web   service文档架构向代理类添加ServiceDescription和XmlSchema                             
  301.         /// </summary>                                  
  302.         /// <param   name="baseWSDLUrl">web服务地址</param>                           
  303.         /// <param   name="importer">代理类</param>                              
  304.         private void checkForImports(string baseWsdlUrl, ServiceDescriptionImporter importer)  
  305.         {  
  306.             DiscoveryClientProtocol dcp = new DiscoveryClientProtocol();  
  307.             dcp.DiscoverAny(baseWsdlUrl);  
  308.             dcp.ResolveAll();  
  309.             foreach (object osd in dcp.Documents.Values)  
  310.             {  
  311.                 if (osd is ServiceDescription) importer.AddServiceDescription((ServiceDescription)osd, null, null); ;  
  312.                 if (osd is XmlSchema) importer.Schemas.Add((XmlSchema)osd);  
  313.             }  
  314.         }  
  315.   
  316.         /// <summary>                           
  317.         /// 复制程序集到指定路径                                
  318.         /// </summary>                                  
  319.         /// <param   name="pathToAssembly">程序集路径</param>                              
  320.         private void copyTempAssembly(string pathToAssembly)  
  321.         {  
  322.             File.Copy(pathToAssembly, this._assPath);  
  323.         }  
  324.   
  325.         private string getMd5Sum(string str)  
  326.         {  
  327.             Encoder enc = System.Text.Encoding.Unicode.GetEncoder();  
  328.             byte[] unicodeText = new byte[str.Length * 2];  
  329.             enc.GetBytes(str.ToCharArray(), 0, str.Length, unicodeText, 0, true);  
  330.             MD5 md5 = new MD5CryptoServiceProvider();  
  331.             byte[] result = md5.ComputeHash(unicodeText);  
  332.             StringBuilder sb = new StringBuilder();  
  333.             for (int i = 0; i < result.Length; i++)  
  334.             {  
  335.                 sb.Append(result[i].ToString("X2"));  
  336.             }  
  337.             return sb.ToString();  
  338.         }  
  339.   
  340.         /// <summary>                           
  341.         /// 是否已经存在该程序集                                
  342.         /// </summary>                                  
  343.         /// <returns>false:不存在该程序集,true:已经存在该程序集</returns>                                
  344.         private bool checkCache()  
  345.         {  
  346.             if (File.Exists(this._assPath))  
  347.             {  
  348.                 return true;  
  349.             }  
  350.             return false;  
  351.         }  
  352.   
  353.         //私有方法,默认取url入口的文件名为类名  
  354.         private static string getWsclassName(string wsdlUrl)  
  355.         {  
  356.             string[] parts = wsdlUrl.Split(‘/‘);  
  357.             string[] pps = parts[parts.Length - 1].Split(‘.‘);  
  358.             return pps[0];  
  359.         }  
  360.         #endregion  
  361.     }  
  362. }  



java接口可以用Object[]类型接收参数 

创建个c#的webservice应用,可以运行本示例