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 - ].Split('?'); return pps[];
}
#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 -;
}
int result = ;
try
{
//result = ts.getOriginalDataCount(unitcode, kno, updatetimefrom, updatetimeto);
string[] args = new string[];
args[] = unitcode;
args[] = kno;
args[] = updatetimefrom;
args[] = updatetimeto;
args[] = scenedetail;
args[] = allflag;
args[] = caseno;
object obj = WebServiceHelper.InvokeWebService(xkWebserveUrl, "getOriginalDataCount", args);
result = (int)obj;
}
catch (Exception ex)
{
//TODO 记录异常信息
logger.Error(ex.ToString());
result = -;
}
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[];
args[] = macAddress;
args[] = installPath;
object obj = WebServiceHelper.InvokeWebService(xkWebserveUrl, "installPositionFeedBack", args);
result = (string)obj;
return result;
}
catch (Exception ex)
{
//TODO 记录异常信息
logger.Error(ex.ToString());
return null;
}
}
}
C# 动态加载WebService的更多相关文章
- Net Core动态加载webservice/WCF
1.动态加载的目的 前端时间和顺丰对接了个项目(PS:顺丰的开发对外能力真的是掉粉),用的webservice 测试时用的无固定IP访问,正式版需要固定IP访问,我的理解是web服务都是全网络可以访问 ...
- Silverlight实用窍门系列:2.Silverlight动态加载外部XML指定地址的WebService---(动态加载外部XML文件中指定的WebService地址)【附带实例源码】
接上节所讲的,Silverlight可以加载外部的XML文件里面的内容,那么我们可不可以在外部XML里面配置一个WebService地址,并且以此加载这个地址来动态加载WebService呢?这样子就 ...
- js动态加载css和js
之前写了一个工具类点此链接里面含有这段代码,感觉用处挺多,特意提出来 var loadUtil = { /* * 方法说明:[动态加载js文件css文件] * 使用方法:loadUtil.loadjs ...
- geotrellis使用(二十三)动态加载时间序列数据
目录 前言 实现方法 总结 一.前言 今天要介绍的绝对是华丽的干货.比如我们从互联网上下载到了一系列(每天或者月平均等)的MODIS数据,我们怎么能够对比同一区域不同时间的数据情况,采用 ...
- Ext JS 如何动态加载JavaScript创建窗体
JavaScript不需要编译即可运行,这让JavaScript构建的应用程序可以变得很灵活.我们可以根据需要动态从服务器加载JavaScript脚本来创建和控制UI来与用户交互.下面结合Ext JS ...
- Ext动态加载Toolbar
在使用Ext的GridPanel时候,有时候需要面板不用重新加载而去更新Store或者Toolbar,Store的方法有很多,例如官方api给我们提供的Store.load(),Store.reLoa ...
- Android动态加载框架汇总
几种动态加载的比较 1.Tinker 用途:热修复 GitHub地址:https://github.com/Tencent/tinker/ 使用:http://www.jianshu.com/p/f6 ...
- 为不同分辨率单独做样式文件,在页面头部用js判断分辨率后动态加载定义好的样式文件
为不同分辨率单独做样式文件,在页面头部用js判断分辨率后动态加载定义好的样式文件.样式文件命名格式如:forms[_屏幕宽度].css,样式文件中只需重新定义文本框和下拉框的宽度即可. 在包含的头文件 ...
- html中的图像动态加载问题
首先要说明下文档加载完成是什么概念 一个页面http请求访问时,浏览器会将它的html文件内容请求到本地解析,从窗口打开时开始解析这个document,页面初始的html结构和里面的文字等内容加载完成 ...
随机推荐
- DPDK l2fwd
dpdk的l2fwd主要做二层转发,代码分析如下. #include <stdio.h> #include <stdlib.h> #include <string.h&g ...
- Pandas缺失数据
数据丢失(缺失)在现实生活中总是一个问题. 机器学习和数据挖掘等领域由于数据缺失导致的数据质量差,在模型预测的准确性上面临着严重的问题. 在这些领域,缺失值处理是使模型更加准确和有效的重点. 何时以及 ...
- JavaEE 技术体系
JavaEE 技术体系总结: 一:常见模式与工具 设计模式,流行的框架与组件 常见的设计模式,编码必备 Spring5,做应用必不可少的最新框架 MyBatis,玩数据库必不可少的组件 二:工程化与工 ...
- WSL安装xfce4
参考:https://github.com/Microsoft/WSL/issues/637 安装组件 1. win10 上安装 Xming https://sourceforge.net/proje ...
- JDBC相关总结
JDBC statement的相关总结 1.Statement.PreparedStatement和CallableStatement都是接口(interface). 2.Statement继承自Wr ...
- Map类集合
集合类 Key Value ...
- cvFindContours函数
cvFindContours函数: int cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour, in ...
- SDRAM引入
SDRAM:Synchronous Dynamic Random Access Memory,同步动态随机存储器. DDR: DDR是DDR SDRAM,是SDRAM的升级版.(DDR:double ...
- java10---点餐系统
public class OrderMsg { public static void main(String[] args) throws Exception { /** * 订餐人姓名.选择菜品.送 ...
- h5使用模块模板,循环输出模块列表
博主使用freemarker为框架,不过不影响功能的说明,首先来看看成品效果图 然后是html [#import "/common/layout.ftl" as layout] [ ...