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结构和里面的文字等内容加载完成 ...
随机推荐
- LeetCode——Find All Numbers Disappeared in an Array
LeetCode--Find All Numbers Disappeared in an Array Question Given an array of integers where 1 ≤ a[i ...
- PHP 开发环境搭建
1. PHP (1) download PHP and extra the zip file to the folder “C:\tools\php” (2) add the path “;C:\to ...
- Firefox 下载、附加组件、Flash插件、缓存位置(附加Chrome下载和Opera下载)
Firefox 下载的FTP页面: http://ftp.mozilla.org/pub/firefox/releases/ Firefox下载官方页面: https://www.mozilla.or ...
- maven setting仓库镜像
国内连接maven官方的仓库更新依赖库,网速一般很慢,收集一些国内快速的maven仓库镜像以备用. 最新更新:2016年11月11日 18:05:40 阿里云提供Maven私服,我把配置文件贴一下,自 ...
- OpenCV人脸检测并把图片写成avi视频
读出某一个文件夹下“jpg”后缀的全部图片后,用的OpenCV自带的人脸检测检测图片中的人脸,调整图片的大小写成一个avi视频. 主要是要记录一下CvVideoWriter的用法和如何从文件夹中读取某 ...
- hdu 5978 To begin or not to begin(概率,找规律)
To begin or not to begin Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java ...
- 【poj2155】Matrix(二维树状数组区间更新+单点查询)
Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...
- 用java网络编程中的TCP方式上传文本文件及出现的小问题
自己今天刚学java网络编程中的TCP传输,要用TCP传输文件时,自己也是遇到了一些问题,抽空把它整理了一下,供自己以后参考使用. 首先在这个程序中,我用一个客户端,一个服务端,从客户端上传一个文本文 ...
- 旧书重温:0day2【11】第6章 狙击windows的异常处理
昨晚经过一番努力,又把第六章的内容温习了一遍! 随手,做了一个实验!狙击windows的异常处理, 顺便也把过程记录了下来!省事!(有图) 今早,论坛一直无法打开! 就推迟到了现在! 哈哈 正题: 第 ...
- 9.链表中倒数第k个结点[FindReverseKthLinkedListNode]
[题目] 输入一个单向链表,输出该链表中倒数第k个结点.链表的倒数第0个结点为链表的尾指针.链表结点定义如下: C++ Code 12345 struct ListNode { int ...