いくつかの方法で動的起動インターフェースのWebService

まず、Webサービスは何ですか?

 ここではそれらを繰り返すと、「====知られたくないポータル

第二に、なぜ動的起動インターフェースのWebServiceべきでしょうか?

一般的にはラインコールに来たC#の開発におけるWebサービスのサービス・インターフェースを参照することにより組み込まれている呼び出して、次の手順を実行します。

1.参照を見つけ、この方法は、さらに後に直接呼び出すことができるWeb参照を追加、サービス参照の追加、高度な検索を右クリックします。

 

 

 

 

この方法が最も簡単で、粗製の方法以上のものです。機械で直接アクセスしませWebServiceが、それはいくつかの卵を傷つける場合はもちろん、必ずしも開発の独り善がりので、サービスへのローカル直接アクセスのアドレス上記の方法です。

それは望ましいことではない。このように、その後、どのような方法は、直接それを開発することができますアクセスできないのでしょうか?呼び出しの動的呼び出しを使用する必要があります。次のステップは、どのように動的な呼び出しWebサービスです。

いくつかの方法で第三に、動的な呼び出しWebサービス

 一つの方法:

Baiduは、それを見つけるためだけの方法は、アップグレードされたパフォーマンスを発見し、最適化するために、百度からコードを取りました。

 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接口的方式,在实际开发中,遇到不能访问的,一般用第二种比较保险。

 

おすすめ

転載: www.cnblogs.com/jiangxifanzhouyudu/p/12008710.html