在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. #regionInvokeWebService
  17. staticstringGetCacheKey(stringurl,
  18. stringclassName)
  19. {
  20. returnurl.ToLower()+className;
  21. }
  22. staticTypeGetTypeFromCache(stringurl,
  23. stringclassName)
  24. {
  25. stringkey=GetCacheKey(url,className);
  26. foreach(KeyValuePair〈string,Type〉
  27. pairin_typeList)
  28. {
  29. if(key==pair.Key)
  30. {
  31. returnpair.Value;
  32. }
  33. }
  34. returnnull;
  35. }
  36. staticTypeGetTypeFromWebService
  37. (stringurl,stringclassName)
  38. {
  39. string@namespace="EnterpriseServerBase.
  40. WebService.DynamicWebCalling";
  41. if((className==null)||(className==""))
  42. {
  43. className=GetWsClassName(url);
  44. }
  45. //获取WSDL
  46. WebClientwc=newWebClient();
  47. Streamstream=wc.OpenRead(url+"?WSDL");
  48. ServiceDescriptionsd=ServiceDescription.
  49. Read(stream);
  50. ServiceDescriptionImportersdi=
  51. newServiceDescriptionImporter();
  52. sdi.AddServiceDescription(sd,"","");
  53. CodeNamespacecn=newCodeNamespace
  54. (@namespace);
  55. //生成客户端代理类代码
  56. CodeCompileUnitccu=newCodeCompileUnit();
  57. ccu.Namespaces.Add(cn);
  58. sdi.Import(cn,ccu);
  59. CSharpCodeProvidercsc=newCSharpCodeProvider();
  60. ICodeCompilericc=csc.CreateCompiler();
  61. //设定编译参数
  62. CompilerParameterscplist=newCompilerParameters();
  63. cplist.GenerateExecutable=false;
  64. cplist.GenerateInMemory=true;
  65. cplist.ReferencedAssemblies.Add
  66. ("System.dll");
  67. cplist.ReferencedAssemblies.Add
  68. ("System.XML.dll");
  69. cplist.ReferencedAssemblies.Add
  70. ("System.Web.Services.dll");
  71. cplist.ReferencedAssemblies.Add
  72. ("System.Data.dll");
  73. //编译代理类
  74. CompilerResultscr=
  75. icc.CompileAssemblyFromDom(cplist,ccu);
  76. if(true==cr.Errors.HasErrors)
  77. {
  78. System.Text.StringBuildersb=
  79. newSystem.Text.StringBuilder();
  80. foreach(System.CodeDom.Compiler.
  81. CompilerErrorceincr.Errors)
  82. {
  83. sb.Append(ce.ToString());
  84. sb.Append(System.Environment.NewLine);
  85. }
  86. thrownewException(sb.ToString());
  87. }
  88. //生成代理实例,并调用方法
  89. System.Reflection.Assemblyassembly=
  90. cr.CompiledAssembly;
  91. Typet=assembly.GetType(@namespace+".
  92. "+className,true,true);
  93. returnt;
  94. }
  95. //动态调用web服务
  96. publicstaticobjectInvokeWebService
  97. (stringurl,stringmethodName,object[]args)
  98. {
  99. returnInvokeWebService(url,null,
  100. methodName,args);
  101. }
  102. publicstaticobjectInvokeWebService(stringurl,
  103. stringclassName,stringmethodName,object[]args)
  104. {
  105. try
  106. {
  107. Typet=GetTypeFromCache(url,className);
  108. if(t==null)
  109. {
  110. t=GetTypeFromWebService(url,className);
  111. //添加到缓冲中
  112. stringkey=GetCacheKey(url,className);
  113. _typeList.Add(key,t);
  114. }
  115. objectobj=Activator.CreateInstance(t);
  116. MethodInfomi=t.GetMethod(methodName);
  117. returnmi.Invoke(obj,args);
  118. }
  119. catch(Exceptionex)
  120. {
  121. thrownewException(ex.InnerException.Message,
  122. newException(ex.InnerException.StackTrace));
  123. }
  124. }
  125. privatestaticstringGetWsClassName(stringwsUrl)
  126. {
  127. string[]parts=wsUrl.Split('/');
  128. string[]pps=parts[parts.Length-1].Split('.');
  129. returnpps[0];
  130. }
  131. #endregion
  132. }
  133. }

上面的注释已经很好的说明了各代码段的功能,下面给个例子看看,这个例子是通过访问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)要漂亮的多。

本文名称:在C#中动态调用WebService
地址分享:http://www.csdahua.cn/qtweb/news43/341843.html

网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网