0
点赞
收藏
分享

微信扫一扫

c# - - - 使用动态代理类调用 WebService,加内存缓存程序集

工具类

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reflection;
using System.Web.Services.Description;

namespace DynamicWebServiceInvoke
{
    public class WebServiceHelper
    {
        // 静态缓存:URL => 已编译的程序集
        private static readonly Dictionary<string, Assembly> AssemblyCache = new Dictionary<string, Assembly>();

        /// <summary>
        /// 动态调用 WebService(带程序集缓存)
        /// </summary>
        public static object InvokeWebService(string url, string classname, string methodname, object[] args)
        {
            Assembly assembly;

            // 1️⃣ 如果缓存中已有,直接使用
            if (AssemblyCache.ContainsKey(url))
            {
                assembly = AssemblyCache[url];
            }
            else
            {
                // 2️⃣ 动态下载并编译 WSDL
                assembly = BuildAssemblyFromWsdl(url);

                // 3️⃣ 存入缓存
                AssemblyCache[url] = assembly;
            }

            // 4️⃣ 反射创建对象并调用方法
            Type t = assembly.GetType("DynamicWebServiceProxy." + classname, true, true);
            object obj = Activator.CreateInstance(t);
            MethodInfo mi = t.GetMethod(methodname);
            return mi.Invoke(obj, args);
        }

        /// <summary>
        /// 从 WSDL 动态生成并编译代理类
        /// </summary>
        private static Assembly BuildAssemblyFromWsdl(string url)
        {
            // 下载 WSDL
            WebClient wc = new WebClient();
            Stream stream = wc.OpenRead(url + "?wsdl");
            ServiceDescription sd = ServiceDescription.Read(stream);
            ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();

            sdi.AddServiceDescription(sd, "", "");
            sdi.ProtocolName = "Soap";
            sdi.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;

            // 生成代码
            CodeNamespace cn = new CodeNamespace("DynamicWebServiceProxy");
            CodeCompileUnit ccu = new CodeCompileUnit();
            ccu.Namespaces.Add(cn);
            sdi.Import(cn, ccu);

            // 编译为程序集
            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
            CompilerParameters cp = new CompilerParameters();
            cp.GenerateExecutable = false;
            cp.GenerateInMemory = true;
            cp.ReferencedAssemblies.Add("System.dll");
            cp.ReferencedAssemblies.Add("System.Web.Services.dll");
            cp.ReferencedAssemblies.Add("System.Xml.dll");
            cp.ReferencedAssemblies.Add("System.Data.dll");

            CompilerResults cr = provider.CompileAssemblyFromDom(cp, ccu);
            if (cr.Errors.HasErrors)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                foreach (CompilerError ce in cr.Errors)
                    sb.AppendLine(ce.ToString());
                throw new Exception("动态编译 WebService 代理类失败:\r\n" + sb.ToString());
            }

            return cr.CompiledAssembly;
        }
    }
}

调用示例

using System;
using DynamicWebServiceInvoke;

class Program
{
    static void Main()
    {
        string url = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx";
        string classname = "WeatherWebService";
        string method = "getWeatherbyCityName";

        // 参数数组
        object[] args = new object[] { "北京" };

        // 第一次调用:会下载 WSDL + 编译代理
        object result1 = WebServiceHelper.InvokeWebService(url, classname, method, args);
        Console.WriteLine("第一次调用结果:");
        PrintResult(result1);

        Console.WriteLine("\n--------------------\n");

        // 第二次调用:直接使用缓存程序集,速度极快
        object result2 = WebServiceHelper.InvokeWebService(url, classname, method, args);
        Console.WriteLine("第二次调用结果(使用缓存):");
        PrintResult(result2);

        Console.ReadLine();
    }

    static void PrintResult(object result)
    {
        if (result == null)
        {
            Console.WriteLine("返回为空");
            return;
        }

        if (result is Array)
        {
            Array arr = (Array)result;
            foreach (object o in arr)
            {
                Console.WriteLine(o);
            }
        }
        else
        {
            Console.WriteLine(result.ToString());
        }
    }
}


举报

相关推荐

0 条评论