/// <summary> /// 将请求消息转换成目标服务的输入参数 /// </summary> /// <param name="asm"></param> /// <param name="request"></param> /// <returns></returns> private static Object GetRequest(SoapClientItem soapClient, ESB.Core.Schema.服务请求 request) { object target = null; try { target = soapClient.CreateRequestObject(); if (target != null) { soapClient.SetReqObjProperty(target, "主机名称", request.主机名称); soapClient.SetReqObjProperty(target, "服务名称", request.服务名称); soapClient.SetReqObjProperty(target, "方法名称", request.方法名称); soapClient.SetReqObjProperty(target, "消息内容", request.消息内容); soapClient.SetReqObjProperty(target, "密码", request.密码); soapClient.SetReqObjProperty(target, "请求时间", request.请求时间); } } catch (Exception ex) { XTrace.WriteLine("构造请求参数失败:" + ex.Message); } return target; }
/// <summary> /// 获取到指定URL的代理程序集 /// </summary> /// <param name="url"></param> /// <returns></returns> public static SoapClientItem GetItem(String url, String serviceName) { if (!s_soapClientDict.ContainsKey(url)) { lock (GetLock(url)) { if (!s_soapClientDict.ContainsKey(url)) { try { SoapClientItem item = LoadAssembly(url, serviceName); s_soapClientDict.Add(url, item); } catch (Exception ex) { XTrace.WriteException(ex); throw ex; } } } } return(s_soapClientDict[url]); }
/// <summary> /// 利用反射调用目标服务 /// </summary> /// <param name="url"></param> /// <param name="request"></param> /// <returns></returns> internal static ESB.Core.Schema.务响应 CallWebService(CallState state) { CallState callState = state as CallState; BindingTemplate binding = callState.Binding; ESB.Core.Schema.务请求 request = callState.Request; SoapClientItem soapClient = null; try { soapClient = SoapClientCache.GetItem(binding.Address, request.务名称); } catch (Exception ex) { throw LogUtil.ExceptionAndLog(callState, "获取目标服务的代理程序集时发生异常", ex.Message, binding, request); } if (soapClient != null) { MethodInfo method = soapClient.GetMethodInfo(request.方法名称); if (method == null) { throw LogUtil.ExceptionAndLog(callState, "目标服务未实现方法", request.方法名称, binding, request); } Object req = GetRequest(soapClient, request); if (req == null) { throw LogUtil.ExceptionAndLog(callState, "无法将请求转换成目标服务所需要的输入参数", "", binding, request); } Object res = null; try { callState.CallBeginTime = DateTime.Now; res = method.Invoke(soapClient.PortObject, new Object[] { req }); callState.CallEndTime = DateTime.Now; } catch (Exception ex) { callState.CallEndTime = DateTime.Now; String message = String.Empty; if (ex.InnerException != null) { message = ex.InnerException.Message; } else { message = ex.Message; } throw LogUtil.ExceptionAndLog(callState, "调用目标服务抛出异常", message, binding, request); } ESB.Core.Schema.务响应 response = GetResponse(res, method.ReturnType); LogUtil.AddAuditLog( 1 , binding , callState.RequestBeginTime, callState.RequestEndTime, callState.CallBeginTime, callState.CallEndTime , response.消息内容, request); return(response); } else { throw LogUtil.ExceptionAndLog(callState, "获取目标服务的代理程序集失败!", "", binding, request); } }
/// <summary> /// 加载代理程序集 /// </summary> /// <param name="url"></param> /// <param name="serviceName"></param> /// <returns></returns> private static SoapClientItem LoadAssembly(String url, String serviceName) { String assemblyPath = GetAssemblyPath(url); String portTypeFullName = String.Empty; // 注意此处要用全名:命名空间.类名 // 如果代理程序集不存在则编译生成代理程序集,否则直接加载 if (!File.Exists(assemblyPath)) { portTypeFullName = CompilerAssembly(url, serviceName, assemblyPath); } else { portTypeFullName = AssemblyType.GetInstance(assemblyPath).PortType; } // 如果没有获取到端口类型则清空程序集缓存并抛出异常 if (portTypeFullName == String.Empty) { ClearCache(url); throw new Exception(String.Format("获取服务:{0}『{1}』的端口类型失败!", serviceName, url)); } Assembly asm = null; using (FileStream fs = File.OpenRead(assemblyPath)) { asm = Assembly.Load(fs.ReadBytes(fs.Length)); // 此处采用文件流进行加载,使得加载后的程序集仍然可以被重新编译 } if (asm == null) { throw new Exception(String.Format("加载代理程序集{0}失败!", assemblyPath)); } //Assembly asm = result.CompiledAssembly; //Type portType = asm.GetType(String.Format("{0}.{1}", serviceName, portTypeName)); //Type reqType = asm.GetType(String.Format("{0}.request", serviceName)); // 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。 Type portType = GetTypeFromAssembly(asm, portTypeFullName, assemblyPath); Type reqType = GetTypeFromAssembly(asm, String.Format("{0}.request", portTypeFullName.Split('.')[0]), assemblyPath); // 创建端口类对象 Object port = Activator.CreateInstance(portType); if (port == null) { throw new Exception(String.Format("创建:{0}『{1}』的端口类型对象失败!", serviceName, url)); } // 将超时设置为10分钟 portType.InvokeMember("Timeout", BindingFlags.SetProperty, null, port, new Object[] { 10 * 60 * 1000 }); SoapClientItem item = new SoapClientItem() { ProxyAssembly = asm, PortObject = port, PortType = portType, RequestType = reqType }; return(item); }
/// <summary> /// 加载代理程序集 /// </summary> /// <param name="url"></param> /// <param name="serviceName"></param> /// <returns></returns> private static SoapClientItem LoadAssembly(String url, String serviceName) { String assemblyPath = GetAssemblyPath(url); String portTypeFullName = String.Empty; // 注意此处要用全名:命名空间.类名 // 如果代理程序集不存在则编译生成代理程序集,否则直接加载 if (!File.Exists(assemblyPath)) { portTypeFullName = CompilerAssembly(url, serviceName, assemblyPath); } else { portTypeFullName = AssemblyType.GetInstance(assemblyPath).PortType; } // 如果没有获取到端口类型则清空程序集缓存并抛出异常 if (portTypeFullName == String.Empty) { ClearCache(url); throw new Exception(String.Format("获取服务:{0}『{1}』的端口类型失败!", serviceName, url)); } Assembly asm = null; using (FileStream fs = File.OpenRead(assemblyPath)) { asm = Assembly.Load(fs.ReadBytes(fs.Length)); // 此处采用文件流进行加载,使得加载后的程序集仍然可以被重新编译 } if (asm == null) throw new Exception(String.Format("加载代理程序集{0}失败!", assemblyPath)); //Assembly asm = result.CompiledAssembly; //Type portType = asm.GetType(String.Format("{0}.{1}", serviceName, portTypeName)); //Type reqType = asm.GetType(String.Format("{0}.request", serviceName)); // 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。 Type portType = GetTypeFromAssembly(asm, portTypeFullName, assemblyPath); Type reqType = GetTypeFromAssembly(asm, String.Format("{0}.request", portTypeFullName.Split('.')[0]), assemblyPath); // 创建端口类对象 Object port = Activator.CreateInstance(portType); if(port == null) throw new Exception(String.Format("创建:{0}『{1}』的端口类型对象失败!", serviceName, url)); // 将超时设置为10分钟 portType.InvokeMember("Timeout", BindingFlags.SetProperty, null, port, new Object[] { 10 * 60 * 1000 }); SoapClientItem item = new SoapClientItem() { ProxyAssembly = asm, PortObject = port, PortType = portType, RequestType = reqType }; return item; }