zoukankan      html  css  js  c++  java
  • WebService的动态调用(C#)

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

    C#代码
    public static object InvokeWebService(string url,  string methodname, object[] args)

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

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

    C#代码
     #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 服务来获取各大城市的天气状况。

    C#代码
         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)要漂亮的多。

  • 相关阅读:
    LeetCode OJ 112. Path Sum
    LeetCode OJ 226. Invert Binary Tree
    LeetCode OJ 100. Same Tree
    LeetCode OJ 104. Maximum Depth of Binary Tree
    LeetCode OJ 111. Minimum Depth of Binary Tree
    LeetCode OJ 110. Balanced Binary Tree
    apache-jmeter-3.1的简单压力测试使用方法(下载和安装)
    JMeter入门教程
    CentOS6(CentOS7)设置静态IP 并且 能够上网
    分享好文:分享我在阿里8年,是如何一步一步走向架构师的
  • 原文地址:https://www.cnblogs.com/SFAN/p/2122509.html
Copyright © 2011-2022 走看看