zoukankan      html  css  js  c++  java
  • 动态调用Webservice

     通常我们在程序中需要调用WebService时,都是通过“添加Web引用”,让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务。这样是使工作简单了,但是却和提供Web服务的URL、方法名、参数绑定在一起了,这是VS.NET自动为我们生成Web服务代理的限制。如果哪一天发布Web服务的URL改变了,则我们需要重新让VS.NET生成代理,并重新编译。在某些情况下,这可能是不能忍受的,我们需要C#中动态调用WebService的能力。比如我们可以把Web服务的URL保存在配置文件中,这样,当服务URL改变时,只需要修改配置文件就可以了。

        说了这么多,实际上我们要实现这样的功能:

    1. public static object InvokeWebService(string url,   
    2. string methodname, object[] args) 

        其中,url是Web服务的地址,methodname是要调用服务方法名,args是要调用Web服务所需的参数,返回值就是web服务返回的结果了。

        要实现这样的功能,你需要这几个方面的技能:反射、CodeDom、编程使用C#编译器、WebService。在了解这些知识后,就可以容易的实现web服务的动态调用了:  

    1. using System.CodeDom.Compiler;  
    2. using System;  
    3. using System.Net;  
    4. using System.CodeDom;  
    5. using Microsoft.CSharp;  
    6. using System.IO;  
    7. using System.Web.Services.Description;  
    8. using System.Collections.Generic;  
    9. using System.Reflection;  
    10. namespace cjl.WebServices  
    11. {  
    12. public class DynamicWebServices  
    13. {  
    14. static SortedList〈string,Type〉_typeList=  
    15. new SortedList〈string,Type〉();  
    16.  
    17. #regionInvokeWebService  
    18.  
    19. static string GetCacheKey(string url,  
    20. string className)  
    21. {  
    22. return url.ToLower()+className;  
    23. }  
    24. static Type GetTypeFromCache(string url,  
    25. string className)  
    26. {  
    27. string key=GetCacheKey(url,className);  
    28. foreach(KeyValuePair〈string,Type〉  
    29. pair in _typeList)  
    30. {  
    31. if(key==pair.Key)  
    32. {  
    33. return pair.Value;  
    34. }  
    35. }  
    36.  
    37. return null;  
    38. }  
    39. static Type GetTypeFromWebService  
    40. (string url,string className)  
    41. {  
    42. string @namespace="EnterpriseServerBase.  
    43. WebService.DynamicWebCalling";  
    44. if((className==null)||(className==""))  
    45. {  
    46. className=GetWsClassName(url);  
    47. }  
    48.  
    49. //获取WSDL  
    50. WebClient wc=new WebClient();  
    51. Stream stream=wc.OpenRead(url+"?WSDL");  
    52. ServiceDescription sd=ServiceDescription.  
    53. Read(stream);  
    54. ServiceDescriptionImporter sdi=  
    55. new ServiceDescriptionImporter();  
    56. sdi.AddServiceDescription(sd,"","");  
    57. CodeNamespace cn=new CodeNamespace  
    58. (@namespace);  
    59.  
    60. //生成客户端代理类代码  
    61. CodeCompileUnit ccu=new CodeCompileUnit();  
    62. ccu.Namespaces.Add(cn);  
    63. sdi.Import(cn,ccu);  
    64. CSharpCodeProvider csc=new CSharpCodeProvider();  
    65. ICodeCompiler icc=csc.CreateCompiler();  
    66.  
    67. //设定编译参数  
    68. CompilerParameters cplist=new CompilerParameters();  
    69. cplist.GenerateExecutable=false;  
    70. cplist.GenerateInMemory=true;  
    71. cplist.ReferencedAssemblies.Add 
    72. ("System.dll");  
    73. cplist.ReferencedAssemblies.Add 
    74. ("System.XML.dll");  
    75. cplist.ReferencedAssemblies.Add 
    76. ("System.Web.Services.dll");  
    77. cplist.ReferencedAssemblies.Add 
    78. ("System.Data.dll");  
    79.  
    80. //编译代理类  
    81. CompilerResults cr=  
    82. icc.CompileAssemblyFromDom(cplist,ccu);  
    83. if(true==cr.Errors.HasErrors)  
    84. {  
    85. System.Text.StringBuildersb=  
    86. new System.Text.StringBuilder();  
    87. foreach(System.CodeDom.Compiler.  
    88. CompilerError ce in cr.Errors)  
    89. {  
    90. sb.Append(ce.ToString());  
    91. sb.Append(System.Environment.NewLine);  
    92. }  
    93. throw new Exception(sb.ToString());  
    94. }  
    95.  
    96. //生成代理实例,并调用方法  
    97. System.Reflection.Assemblyassembly=  
    98. cr.CompiledAssembly;  
    99. Type t=assembly.GetType(@namespace+".  
    100. "+className,true,true);  
    101. return t;  
    102. }  
    103.  
    104. //动态调用web服务  
    105. public static object InvokeWebService  
    106. (string url,string methodName,object[]args)  
    107. {  
    108. return InvokeWebService(url,null,  
    109. methodName,args);  
    110. }  
    111.  
    112. public static object InvokeWebService(string url,  
    113. string className,string methodName,object[]args)  
    114. {  
    115. try  
    116. {  
    117. Type t=GetTypeFromCache(url,className);  
    118. if(t==null)  
    119. {  
    120. t=GetTypeFromWebService(url,className);  
    121.  
    122. //添加到缓冲中  
    123. stringkey=GetCacheKey(url,className);  
    124. _typeList.Add(key,t);  
    125. }  
    126.  
    127. object obj=Activator.CreateInstance(t);  
    128. MethodInfo mi=t.GetMethod(methodName);  
    129. return mi.Invoke(obj,args);  
    130. }  
    131. catch(Exception ex)  
    132. {  
    133. throw new Exception(ex.InnerException.Message,  
    134. new Exception(ex.InnerException.StackTrace));  
    135. }  
    136. }  
    137. private static string GetWsClassName(string wsUrl)  
    138. {  
    139. string []parts=wsUrl.Split('/');  
    140. string []pps=parts[parts.Length-1].Split('.');  
    141. return pps[0];  
    142. }  
    143. #endregion  
    144. }  
    145. }  

        上面的注释已经很好的说明了各代码段的功能,下面给个例子看看,这个例子是通过访问http://www.webservicex.net/globalweather.asmx服务来获取各大城市的天气状况。              

    1. string url = "http://www.webservicex.  
    2. net/globalweather.asmx";  
    3. string[] args = new string[2];  
    4. args[0] = this.textBox_CityName.Text;  
    5. args[1] = "China";  
    6. object result = WebServiceHelper.  
    7. InvokeWebService(url, "GetWeather", args);  
    8. this.label_Result.Text = result.ToString();  

        上述的例子中,调用web服务使用了两个参数,第一个是城市的名字,第二个是国家的名字,Web服务返回的是XML文档,可以从其中解析出温度、风力等天气情况。

        最后说一下,C#虽然仍属于静态语言之列,但是其动态能力也是很强大的,不信,你可以看看Spring.net的AOP实现,这种“无侵入”的AOP实现比通常的.NET声明式AOP实现(一般是通过AOP Attribute)要漂亮的多。

  • 相关阅读:
    异步调用WCF的方法需要小心的地方
    常用处理字符串的SQL函数
    SQL分页的几种方式
    初学WCF需要注意的地方
    关于搭建Session服务器(转载)
    PowerDesigner通过SQL语句生成PDM文件并将name和comment进行互相转换
    VMware15安装Centos7超详细过程
    sql server死锁查询及清理
    html 灯笼
    相机曝光与增益
  • 原文地址:https://www.cnblogs.com/hxwzwiy/p/2412298.html
Copyright © 2011-2022 走看看