通常我们在程序中需要调用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)要漂亮的多。

转载于:https://www.cnblogs.com/youan/archive/2011/03/12/1982436.html

【随记】动态调用web服务相关推荐

  1. C#动态调用web服务 远程调用技术WebService

    一.课程介绍 一位伟大的讲师曾经说过一句话:事物存在即合理!意思就是说:任何存在的事物都有其存在的原因,存在的一切事物都可以找到其存在的理由,我们应当把焦点放在因果关联的本质上.所以在本次分享课开课之 ...

  2. 通过数据库存储过程调用Web服务的办法

    Web服务概览 Web服务,从广义而言,就是在两个应用或电子设备之间通过万维网通信的方法.Web服务有两种类型:简单对象访问协议(SOAP)以及表述性状态转移(REST). SOAP为基于XML的消息 ...

  3. asmx 接受 ajax post,jQuery ajax调用web服务(asmx)触发认证弹出框

    在我的asp.net 4.0电子商务web应用程序中,登录的客户可以点击锚点,如"过去6个月内的订单"或"订单去年"来查看他过去的订单.当点击这样的锚,我做一个 ...

  4. android10获取手机号码,【android,10】10.调用web服务获取手机号码归属地

    一.调用 web 服务获取号码归属地: 1.设置布局: android:layout_width="fill_parent" android:layout_height=" ...

  5. 异步调用Web服务方法

    基于Ajax技术构建的门户是web 2.0这一代中最为成功的Web应用程序.而这块市场上iGoogle和Pageflakes这两大站点已经走在了时代的前列. 当你打开Pageflakes,将会看到如下 ...

  6. GDC服务器主机与证书不匹配,调用web服务soap时,错误https URL主机名与客户端信任库中服务器证书上的公用名(CN)不匹配...

    嘿,我想用SAAJ调用soap web服务 我用野蝇10 我试图将此系统属性添加到standalone.xml,但无法工作 20: 53:08208错误[stderr](默认任务-21),原因是:ja ...

  7. 动态调用Web Service

    代码  System.Net.WebClient wc = new System.Net.WebClient();         System.IO.Stream stream = wc.OpenR ...

  8. 动态调用WCF服务[转]

    原文地址:http://blog.csdn.net/castlooo/archive/2010/05/06/5562619.aspx 客户端调用wcf ,有时需要动态的调用服务端的WCF中的方法,本方 ...

  9. ajax web服务调用无效 参数值,json调用web服务,报错,无参数值!

    前台:ShowDetail("英伦学院派马夹"); function ShowDetail(productId) { // make an ajax call to the web ...

最新文章

  1. 3. 定义10个字节的键盘缓冲区,然后键盘输入字符填满该缓冲区,做如下工作: (1)分别将输入键盘缓冲区的字符按数字,小写字母,大写字母,其他字符进行计数; 分别将这些计数值显示出来。 (2)分别将这
  2. 为CDH 5.7集群添加Kerberos身份验证及Sentry权限控制
  3. RabbitMQ学习之spring-amqp的重要类的认识
  4. linux下多线程的创建与等待详解 【转载】
  5. mysql join 组合索引,图文详解MySQL中两表关联的连接表如何创建索引
  6. GBDT 特征提取(2)
  7. matlab的图像滤波,Matlab实现图像滤波
  8. 怎么查二手华为手机价格
  9. linux更新电池驱动下载,Linux 5.13电源管理与ACPI更新已提交
  10. 在一张图片的某个特定位置添加另外一张图片
  11. 现在证券公司内部各部门详解
  12. B站视频怎么下载?提取视频文稿的简单方法!
  13. Acwing-4656. 技能升级
  14. VS2017 C++控制台程序不用加pch.h
  15. 《商君列传第八》–读书总结
  16. 后端使用SpringBoot和Jwt工具与Redis数据库+前端Vue Element Admin实现用户携带token的登录功能案例
  17. 简单园区网络基本架构
  18. 如何理解奇偶校验只能发现数据代码中奇数位出错的情况
  19. windows下批处理文件bat怎么写?
  20. 新型循环神经网络IndRNN:可构建更长更深的RNN

热门文章

  1. Docker的使用(一:Docker入门程序)
  2. win10如何查看NVIDIA驱动的版本
  3. 【oracle】dblink创建
  4. 图解eclipse+myeclipse完全绿色版制作过程
  5. javascript数据结构与算法-队列
  6. 第一章 软件自动化测试的基础知识
  7. JAVA的get post 区别
  8. 建立名称server
  9. mysql备份策略的制定
  10. WinAPI: SetRect 及初始化矩形的几种办法