在C#中动态调用WebService

开发 后端
通常我们在程序中需要调用WebService时,都是通过“添加Web引用”。本文向您介绍使用C#中动态调用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. usingSystem.CodeDom.Compiler;  
  2. usingSystem;  
  3. usingSystem.Net;  
  4. usingSystem.CodeDom;  
  5. usingMicrosoft.CSharp;  
  6. usingSystem.IO;  
  7. usingSystem.Web.Services.Description;  
  8. usingSystem.Collections.Generic;  
  9. usingSystem.Reflection;  
  10. namespacecjl.WebServices  
  11. {  
  12. publicclassDynamicWebServices  
  13. {  
  14. staticSortedList〈string,Type〉_typeList=  
  15. newSortedList〈string,Type〉();  
  16.  
  17. #regionInvokeWebService  
  18.  
  19. staticstringGetCacheKey(stringurl,  
  20. stringclassName)  
  21. {  
  22. returnurl.ToLower()+className;  
  23. }  
  24. staticTypeGetTypeFromCache(stringurl,  
  25. stringclassName)  
  26. {  
  27. stringkey=GetCacheKey(url,className);  
  28. foreach(KeyValuePair〈string,Type〉  
  29. pairin_typeList)  
  30. {  
  31. if(key==pair.Key)  
  32. {  
  33. returnpair.Value;  
  34. }  
  35. }  
  36.  
  37. returnnull;  
  38. }  
  39. staticTypeGetTypeFromWebService  
  40. (stringurl,stringclassName)  
  41. {  
  42. string@namespace="EnterpriseServerBase.  
  43. WebService.DynamicWebCalling";  
  44. if((className==null)||(className==""))  
  45. {  
  46. className=GetWsClassName(url);  
  47. }  
  48.  
  49. //获取WSDL  
  50. WebClientwc=newWebClient();  
  51. Streamstream=wc.OpenRead(url+"?WSDL");  
  52. ServiceDescriptionsd=ServiceDescription.  
  53. Read(stream);  
  54. ServiceDescriptionImportersdi=  
  55. newServiceDescriptionImporter();  
  56. sdi.AddServiceDescription(sd,"","");  
  57. CodeNamespacecn=newCodeNamespace  
  58. (@namespace);  
  59.  
  60. //生成客户端代理类代码  
  61. CodeCompileUnitccu=newCodeCompileUnit();  
  62. ccu.Namespaces.Add(cn);  
  63. sdi.Import(cn,ccu);  
  64. CSharpCodeProvidercsc=newCSharpCodeProvider();  
  65. ICodeCompilericc=csc.CreateCompiler();  
  66.  
  67. //设定编译参数  
  68. CompilerParameterscplist=newCompilerParameters();  
  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. CompilerResultscr=  
  82. icc.CompileAssemblyFromDom(cplist,ccu);  
  83. if(true==cr.Errors.HasErrors)  
  84. {  
  85. System.Text.StringBuildersb=  
  86. newSystem.Text.StringBuilder();  
  87. foreach(System.CodeDom.Compiler.  
  88. CompilerErrorceincr.Errors)  
  89. {  
  90. sb.Append(ce.ToString());  
  91. sb.Append(System.Environment.NewLine);  
  92. }  
  93. thrownewException(sb.ToString());  
  94. }  
  95.  
  96. //生成代理实例,并调用方法  
  97. System.Reflection.Assemblyassembly=  
  98. cr.CompiledAssembly;  
  99. Typet=assembly.GetType(@namespace+".  
  100. "+className,true,true);  
  101. returnt;  
  102. }  
  103.  
  104. //动态调用web服务  
  105. publicstaticobjectInvokeWebService  
  106. (stringurl,stringmethodName,object[]args)  
  107. {  
  108. returnInvokeWebService(url,null,  
  109. methodName,args);  
  110. }  
  111.  
  112. publicstaticobjectInvokeWebService(stringurl,  
  113. stringclassName,stringmethodName,object[]args)  
  114. {  
  115. try  
  116. {  
  117. Typet=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. objectobj=Activator.CreateInstance(t);  
  128. MethodInfomi=t.GetMethod(methodName);  
  129. returnmi.Invoke(obj,args);  
  130. }  
  131. catch(Exceptionex)  
  132. {  
  133. thrownewException(ex.InnerException.Message,  
  134. newException(ex.InnerException.StackTrace));  
  135. }  
  136. }  
  137. privatestaticstringGetWsClassName(stringwsUrl)  
  138. {  
  139. string[]parts=wsUrl.Split('/');  
  140. string[]pps=parts[parts.Length-1].Split('.');  
  141. returnpps[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)要漂亮的多。

【编辑推荐】

  1. 如何使用C#创建WebService
  2. C# WebService更新客户端软件
  3. 简明教程 C# Webservice实例
  4. C# Web Service异常处理的两个常见问题
  5. Web Services&XML:什么是Web Service
责任编辑:冰荷 来源: 比特网
相关推荐

2015-07-09 10:44:48

C#WebService

2009-08-06 17:57:14

C# webServiC# WebServi

2009-08-12 18:14:00

C# WebServi

2009-08-07 13:55:35

Java客户端类调用C# WebServi

2009-08-03 11:32:49

C#调用COM对象

2009-08-06 16:44:03

C#创建WebServ

2009-08-05 16:29:18

C#调用C++动态链接

2009-08-06 17:45:08

C# Webservi

2009-08-07 14:10:13

C# WebserviDelphi

2024-03-01 20:59:11

C#DLL开发

2009-07-02 10:07:24

C# 4.0的动态类型Visual Stud

2009-08-11 14:16:00

Winform调用WEC#

2009-08-17 16:18:47

C#调用CreateO

2023-08-02 10:10:00

C#C++

2009-08-05 16:49:42

C#中调用dll

2009-08-06 17:12:13

C# WebServi

2009-07-31 15:47:20

Win32 APIC#

2009-08-20 10:34:46

C#中声明API函数

2009-02-03 09:33:26

动态类型动态编程C# 4.0

2009-08-18 13:22:55

C#动态调用Web服务
点赞
收藏

51CTO技术栈公众号