• 动态生成WebService的客户端


    给定了WebService地址和调用接口后动态的生成DLL,第二次再请求时会先判断DLL是否存在,以提高执行效率

    核心代码下:

    /// <summary>
            /// 动态生成WebService服务客户端
            /// </summary>
            /// <param name="serviceProvider">WebService服务的提供者</param>
            /// <param name="url">WebService具体地址</param>
            /// <param name="serviceName">需要调用的类名</param>
            /// <param name="actionName">需要请求的方法</param>
            /// <param name="args">方法参数列表</param>
            /// <returns></returns>
            public static object InvokeWebService(string serviceProvider, string url, string serviceName, string actionName, object[] args)
            {
                if (string.IsNullOrEmpty(url))
                {
                    throw new ArgumentNullException("url");
                }
    
                if (string.IsNullOrEmpty(serviceName))
                {
                    serviceName = GetWsClassName(url);
                }
    
                var shortUrl = BuildShortUrl(url);
    
                var nameSpace = string.Format("{0}_{1}_{2}", serviceProvider, serviceName, shortUrl);
                var binDir = HttpRuntime.AppDomainId == null ? AppDomain.CurrentDomain.BaseDirectory : HttpRuntime.BinDirectory;
                var asmFullPath = System.IO.Path.Combine(binDir, string.Format("{0}.dll", nameSpace));
    
                #region
                if (!File.Exists(asmFullPath))
                {
                    if (!url.ToLower().EndsWith("?wsdl"))
                    {
                        url += "?wsdl";
                    }
    
                    //获取WSDL 
                    WebClient webClient = new WebClient();
    
                    try
                    {
                        #region 动态生成DLL
                        Stream wsdlStream = webClient.OpenRead(url);
    
                        //服务描述
                        ServiceDescription serviceDesc = ServiceDescription.Read(wsdlStream);
    
                        //生成客户端代理类
                        ServiceDescriptionImporter clientBuilder = new ServiceDescriptionImporter()
                        {
                            CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateNewAsync | System.Xml.Serialization.CodeGenerationOptions.GenerateProperties,
                            ProtocolName = "Soap",
                            Style = ServiceDescriptionImportStyle.Client
                        };
                        clientBuilder.AddServiceDescription(serviceDesc, null, null);
    
    
                        //生成客户端代理类代码
                        CodeNamespace ns = new CodeNamespace(nameSpace);
                        CodeCompileUnit ccu = new CodeCompileUnit();
                        ccu.Namespaces.Add(ns);
    
                        //按照clientBuilder的配置来生成代码
                        clientBuilder.Import(ns, ccu);
    
                        //C#代码容器
                        var sourceCodeProvider = new CSharpCodeProvider();
    
                        //设定编译参数
                        var comParams = new CompilerParameters();
                        comParams.GenerateExecutable = false;//如果此属性的值为 false,则生成 DLL
                        comParams.GenerateInMemory = false;
                        comParams.OutputAssembly = asmFullPath; // 可以指定你所需的任何文件名。
                        comParams.ReferencedAssemblies.Add("System.dll");
                        comParams.ReferencedAssemblies.Add("System.XML.dll");
                        comParams.ReferencedAssemblies.Add("System.Web.Services.dll");
                        comParams.ReferencedAssemblies.Add("System.Data.dll");
                        comParams.CompilerOptions = "/optimize";
    
                        //编译                 
                        var comResult = sourceCodeProvider.CompileAssemblyFromDom(comParams, ccu);
    
                        if (comResult.Errors.HasErrors)
                        {
                            System.Text.StringBuilder sb = new System.Text.StringBuilder();
    
                            foreach (System.CodeDom.Compiler.CompilerError ce in comResult.Errors)
                            {
                                sb.Append(ce.ToString());
                                sb.Append(System.Environment.NewLine);
                            }
    
                            throw new Exception(sb.ToString());
                        }
                        #endregion
                    }
                    catch (Exception ex)
                    {
                    }
                    finally
                    {
                        webClient.Dispose();
                    }
                }
                #endregion
    
                //生成代理实例,并调用方法
                var asm = System.Reflection.Assembly.LoadFile(asmFullPath);
                Type t = asm.GetType(nameSpace + "." + serviceName, true, true);
                object obj = Activator.CreateInstance(t);
                System.Reflection.MethodInfo mi = t.GetMethod(actionName);
                return mi.Invoke(obj, args);
            }
    View Code

    辅助代码:简化WebService地址,类似生成短链的功能

    // Hash an input string and return the hash as
            // a 32 character hexadecimal string.
            static string getMd5Hash(string input)
            {
                // Create a new instance of the MD5CryptoServiceProvider object.
                System.Security.Cryptography.MD5 md5Hasher = System.Security.Cryptography.MD5.Create();
    
                // Convert the input string to a byte array and compute the hash.
                byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
    
                // Create a new Stringbuilder to collect the bytes
                // and create a string.
                StringBuilder sBuilder = new StringBuilder();
    
                // Loop through each byte of the hashed data
                // and format each one as a hexadecimal string.
                for (int i = 0; i < data.Length; i++)
                {
                    sBuilder.Append(data[i].ToString("x2"));
                }
    
                // Return the hexadecimal string.
                return sBuilder.ToString();
            }
    
            static string BuildShortUrl(string url)
            {
                // 可以自定义生成 MD5 加密字符传前的混合 KEY
    
                string key = "fF{#E@#:RJP(#!$";
    
                // 要使用生成 URL 的字符
                string[] chars = new string[] { "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" ,
                  "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" ,
                  "u" , "v" , "w" , "x" , "y" , "z" , "0" , "1" , "2" , "3" , "4" , "5" ,
                  "6" , "7" , "8" , "9" , "A" , "B" , "C" , "D" , "E" , "F" , "G" , "H" ,
                  "I" , "J" , "K" , "L" , "M" , "N" , "O" , "P" , "Q" , "R" , "S" , "T" ,
                  "U" , "V" , "W" , "X" , "Y" , "Z"};
    
                // 对传入网址进行 MD5 加密
                string hex = getMd5Hash(url + key);
    
                string[] resUrl = new string[4];
    
                for (int i = 0; i < 4; i++)
                {
                    // 把加密字符按照 8 位一组 16 进制与 0x3FFFFFFF 进行位与运算
                    string sTempSubString = hex.Substring(i * 8, 8);
    
                    // 这里需要使用 long 型来转换,因为 Inteper .parseInt() 只能处理 31 位 , 首位为符号位 , 如果不用 long ,则会越界
                    long lHexLong = 0x3FFFFFFF & long.Parse(sTempSubString, System.Globalization.NumberStyles.AllowHexSpecifier);
    
                    string outChars = "";
    
                    for (int j = 0; j < 2; j++)
                    {
                        // 把得到的值与 0x0000003D 进行位与运算,取得字符数组 chars 索引
                        long index = 0x0000003D & lHexLong;
    
                        // 把取得的字符相加
                        outChars += chars[(int)index];
    
                        // 每次循环按位右移 7 位
                        lHexLong = lHexLong >> 7;
                    }
    
                    // 把字符串存入对应索引的输出数组
                    resUrl[i] = outChars;
                }
    
                return string.Join("", resUrl);
            }
    View Code

    测试结果:

  • 相关阅读:
    asp.net core-15.Individual authentication 模板
    Thread,Task,async/await,IAsyncResult
    asp.net core-14.JWT认证授权 生成 JWT Token
    asp.net core-13.Cookie-based认证实现
    asp.net core-12.dotnet watch run 和attach到进程调试
    asp.net core-11.WebHost的配置
    asp.net core-10.Http请求的处理过程
    asp.net core-9.依赖注入的使用
    asp.net core-8. 配置的热更新
    asp.net core-7.在Core Mvc中使用Options
  • 原文地址:https://www.cnblogs.com/smlheart/p/3591916.html
Copyright © 2020-2023  润新知