zoukankan      html  css  js  c++  java
  • 动态调用WebService接口的几种方式

    一、什么是WebService?

     这里就不再赘述了,想要了解的====》传送门

    二、为什么要动态调用WebService接口?

    一般在C#开发中调用webService服务中的接口都是通过引用过来就行调用的,步骤如下:

    1.找到引用,右击添加服务引用,找到高级,添加web引用,添加之后就可以直接调用里面的方法。

     

     

     

    以上这种方法是最简单粗暴的一种方式。当然在开发中总是不那么如意,以上方式是在本机直接可以访问服务的地址,假如在本机不能直接访问WebService,那么就会有些蛋疼。

    这种方式就不可取了,那么有什么方式可以不直接访问就可以开发呢?这就要使用动态调用的方式进行调用了。接下来就是如何动态调用WebService了。

    三、动态调用WebService的几种方式

     方式一:

    随便百度一下就可以找到的一种,接下了的代码来源于百度找到的并性能进行优化升级过。

     public static class CommonServiceHelper
        {
            /// <summary>
            /// 静态缓存字典,速度提升至8倍
            /// </summary>
            private static Dictionary<string, object> _webServiceConfig = new Dictionary<string, object>();
    
            //获取WSDL
            private static readonly WebClient wc = new WebClient();
    
            /// < summary>
            /// 动态调用web服务
            /// </summary>
            /// < param name="url">WSDL服务地址</param>
            /// < param name="classname">类名</param>
            /// < param name="methodname">方法名</param>
            /// < param name="args">参数</param>
            /// < returns></returns>
            public static object InvokeWebService(this string url, string methodname, object[] args, string classname = "")
            {
                string key = $"{url}_{methodname}";//缓存Key唯一标识
                Type webService;
                if (!_webServiceConfig.ContainsKey(key))
                {
                    string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
                    //classname 一般自己指定 如果有些地址是http://www.webxml.com.cn/WebServices/WeatherWS?wsdl 就会调用失败
                    if ((classname == null) || (classname == ""))
                    {
                        classname = GetWsClassName(url);
                    }
                    try
                    {
                        Stream stream = wc.OpenRead(url);
                        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 icc = new CSharpCodeProvider();
                        CompilerParameters cplist = new CompilerParameters
                        {
                            GenerateExecutable = false,
                            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 compiler = icc.CompileAssemblyFromDom(cplist, ccu);
                        icc.Dispose();
                        if (compiler.Errors.HasErrors)
                        {
                            System.Text.StringBuilder sb = new System.Text.StringBuilder();
                            foreach (CompilerError ce in compiler.Errors)
                            {
                                sb.Append(ce.ToString());
                                sb.Append(Environment.NewLine);
                            }
                            throw new Exception(sb.ToString());
                        }
                        System.Reflection.Assembly assembly = compiler.CompiledAssembly;
                        Type t = assembly.GetType(@namespace + "." + classname, true, true);
                        webService = t;
                        _webServiceConfig.Add(key, webService);//加入缓存
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(ex.Message);
                    }
                }
                else
                {
                    webService = _webServiceConfig[key] as Type;//获取缓存的数据
                }
                if (webService != null)
                {
                    object obj = Activator.CreateInstance(webService);
                    System.Reflection.MethodInfo mi = webService.GetMethod(methodname);
                    if (mi != null)
                    {
                        return mi.Invoke(obj, args);
                    }
                    throw new Exception($"找不到{methodname}这个方法,调用失败");
                }
                else
                {
                    throw new Exception($"WebService 对象为空,调用失败");
                }
            }
    
            /// <summary>
            /// 获取wsdl类名称
            /// </summary>
            /// <param name="wsUrl">wsdl地址</param>
            /// <returns></returns>
            private static string GetWsClassName(string wsUrl)
            {
                string[] parts = wsUrl.Split('/');
                string[] pps = parts[parts.Length - 1].Split('.');//classname 一般自己指定 原因是因为在这里
                return pps[0];
            }
            /// <summary>
            /// 清空缓存
            /// </summary>
            public static void ClearCache()
            {
                _webServiceConfig.Clear();
            }
        }

     以上方法是第一种,这种方法不是万能的,因为方法是通过反射调用的,多个参数的时候顺序不能乱,方法名称不能写错,对于有些WebService是无法调用的。

    方式二:

    这种方式针对本机不能访问的WebService非常有效,参数啥的不容易搞混,跟C#直接添加引用之后调用方式一样。

    C#添加引用的方式是通过对于WebService的xml进行解析并生成相关代码,根据原理可知,只要有WebService的xml就好办了。

    对于本机不能访问的WebService,找个可以访问的环境,用浏览器进行访问,后面加上wsdl,例如:http://www.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl

    然后进行访问,把页面另存为你可以找得到的地方。我这里直接存储到D盘

    把这个xml文件丢到你本地随便一个可以访问的的站点下,这个xml文件要可以正常访问。(这个很重要)

     接下来就要使用visual studio 开发人员命令工具,我这里是使用vs2019 ,前面几个版本的vs都可以

    在开始菜单里面找到并打开

     接下来使用命令生成代码。

    命令如下:wsdl  你本地访问的那个xml地址全路径                                     

    我这里是放在端口81的站点下

    生成的cs类文件跟通过web引用生成的cs文件是一样,这样就可以解决本机不能直接访问WebService不能调用方法的问题。

    当然,想要可以执行其中的方法还需要把代码放到对应环境上才能执行。

    四、总结

    以上是使用两种方式动态调用WebService接口的方式,在实际开发中,遇到不能访问的,一般用第二种比较保险。

  • 相关阅读:
    Exercise02_09
    Exercise02_05
    Exercise02_01
    Exercise02_03
    Exercise02_07
    web.xml配置详解
    面对不成功的人生
    请不以结婚为目的的恋爱吧
    年轻人能为世界做点什么
    不作就不会活
  • 原文地址:https://www.cnblogs.com/jiangxifanzhouyudu/p/12008710.html
Copyright © 2011-2022 走看看