zoukankan      html  css  js  c++  java
  • C# 动态加载WebService

    项目中需要用到WebService的方式来进行两个服务之间的方法调用,之前都是在项目中添加服务引用的方式来实现,但是这种方式有一个弊端,就是如果提供WebService服务的一方的IP、端口一旦变更,

    调用的一方代码就需要重新编译部署,实际使用不是很方便,因此就采用了下面的方法,通过在代码中动态加载WebService的方式,把IP地址、端口都做成配置项。这样如果只是url的ip和端口出现变更,

    就不需要再去重新编译代码了。

    具体代码如下:

        public static class WebServiceHelper
        {
            static SortedList<string, Type> _typeList = new SortedList<string, Type>();
    
            #region InvokeWebService
    
            static string GetCacheKey(string url, string className)
            {
                return url.ToLower() + className;
            }
            static Type GetTypeFromCache(string url, string className)
            {
                string key = GetCacheKey(url, className);
                foreach (KeyValuePair<string, Type> pair in _typeList)
                {
                    if (key == pair.Key)
                    {
                        return pair.Value;
                    }
                }
    
                return null;
            }
            static Type GetTypeFromWebService(string url, string className)
            {            
                if ((className == null) || (className == ""))
                {
                    className = GetWsClassName(url);
                }
    
                //获取WSDL
                WebClient wc = new WebClient();
                Stream stream = wc.OpenRead(url);
                ServiceDescription sd = ServiceDescription.Read(stream);
    
                ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
                sdi.AddServiceDescription(sd, "", "");            
                CodeNamespace cn = new CodeNamespace();
    
                //生成客户端代理类代码
                CodeCompileUnit ccu = new CodeCompileUnit();
                ccu.Namespaces.Add(cn);
                sdi.Import(cn, ccu);
                CSharpCodeProvider csc = new CSharpCodeProvider();            
    
                //设定编译参数
                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 = csc.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(className, true, true);
    
                return t;
            }
    
            /// <summary>
            /// 动态调用web服务
            /// </summary>
            /// <param name="url">WebService地址</param>
            /// <param name="methodName">需要调用的方法</param>
            /// <param name="args">方法用到的参数列表(需要按照顺序)</param>
            /// <returns></returns>
    
            public static object InvokeWebService(string url, string methodName, object[] args)
            {
                return InvokeWebService(url, null, methodName, args);
            }
    
            public static object InvokeWebService(string url, string className, string methodName, object[] args)
            {
                try
                {
                    Type t = GetTypeFromCache(url, className);
                    if (t == null)
                    {
                        t = GetTypeFromWebService(url, className);
    
                        //添加到缓冲中
                        string key = GetCacheKey(url, className);
                        _typeList.Add(key, t);
                    }
    
                    object obj = Activator.CreateInstance(t);
                    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
        }

    这是最底层的方法类,在实际使用中,我又在上层封装了一个具体接口方法调用的类,示例如下:

        public class WebHelper
        {
    
            ServiceReference.findSceneVideoDataServicePortTypeClient ts = new ServiceReference.findSceneVideoDataServicePortTypeClient();
            LogPrn logger = new LogPrn("WebHelper");
    
            //现勘webservice地址
            private string xkWebserveUrl = "";
    
            public WebHelper(string webserveurl)
            {
                xkWebserveUrl = webserveurl; 
            }
            
    
                 
            /// <summary>
            /// 数量获取服务
            /// </summary>
            /// <param name="unitcode">六位单位代码(选填)</param>
            /// <param name="kno">关联编号(选填)</param>
            /// <param name="updatetimefrom">起始时间(yyyy-mm-dd HH:MM:SS)(选填)</param>
            /// <param name="updatetimeto">结束时间(yyyy-mm-dd HH:MM:SS)(选填)</param>
            /// <param name="scenedetail">发案地点(选填)</param>
            /// <param name="allflag">查询范围(必填)</param>
            /// <param name="caseno">案件编号(A号)(选填)</param>
            /// <returns>-1:单位代码必须为6位数字;
            /// -2:时间不符合格式:yyyy-mm-dd HH:MM:SS;
            /// n(n>=0):根据条件查询结果数量;
            /// -3:其他异常</returns>
            /// <summary> 
            public int getOriginalDataCount(string unitcode, string kno, string updatetimefrom, string updatetimeto, string scenedetail, string allflag, string caseno)
            {
                //if(string.IsNullOrEmpty(unitcode))
                //{
                //    return -3;
                //}
                if (string.IsNullOrEmpty(allflag))
                {
                    return -3;
                }
                int result = 0;
                try
                {               
                    //result = ts.getOriginalDataCount(unitcode, kno, updatetimefrom, updatetimeto); 
                    string[] args = new string[7];
                    args[0] = unitcode;
                    args[1] = kno;
                    args[2] = updatetimefrom;
                    args[3] = updatetimeto;
                    args[4] = scenedetail;
                    args[5] = allflag;
                    args[6] = caseno;
                    object obj = WebServiceHelper.InvokeWebService(xkWebserveUrl, "getOriginalDataCount", args);
                    result = (int)obj;
                }
                catch (Exception ex)
                {
                    //TODO 记录异常信息
                    logger.Error(ex.ToString());
                    result = -3;
                }
                return result;
            }
    
            
    
          
            /// <summary>
            /// 安装位置信息反馈
            /// </summary>
            /// <param name="macAddress">Mac地址(必填)</param>
            /// <param name="installPath">视频客户端安装路径(必填),绝对路径,要精确到exe文件</param>
            /// <returns>1.反馈成功,0.反馈失败,-1.mac地址格式不正确,-2.安装路径格式不正确</returns>
            public string InstallPositionFeedBack(string macAddress, string installPath)
            {
                if (string.IsNullOrEmpty(macAddress) || string.IsNullOrEmpty(installPath))
                {
                    return null;
                }
                string result = "";
                try
                {                
                    string[] args = new string[2];
                    args[0] = macAddress;
                    args[1] = installPath;
                    object obj = WebServiceHelper.InvokeWebService(xkWebserveUrl, "installPositionFeedBack", args);
                    result = (string)obj;
                    return result;
                }
                 catch (Exception ex)
                {
                    //TODO 记录异常信息
                    logger.Error(ex.ToString());
                    return null;
                }
            }
        }
  • 相关阅读:
    EF CodeFirst EntityTypeConfiguration 自关联映射配置
    DDD 领域驱动设计-看我如何应对业务需求变化,领域模型调整?
    DDD 领域驱动设计-看我如何应对业务需求变化,愚蠢的应对?
    【记录】ASP.NET XSS 脚本注入攻击
    【记录】JS 获取图片原始尺寸-防止图片溢出
    让 ASP.NET vNext 在 Mac OS 中飞呀飞。。。
    Building Modern Web Apps-构建现代的 Web 应用程序(一些感想)
    【记录】ASP.NET MVC RegisterBundles
    【记录】JS 生成 URL 二维码
    关于有默认值的字段在用EF做插入操作时的思考(续)
  • 原文地址:https://www.cnblogs.com/tlduck/p/6159581.html
Copyright © 2011-2022 走看看