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结构和里面的文字等内容加载完成 ...
随机推荐
- 洛谷P4311 士兵占领
题目描述 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵 ...
- Docker 容器内配置Tomcat manager 远程控制
下载tomcat镜像 , docker run it docker exec -ti 容器ID /bin/bash 进入容器 apt-get update , apt-get install vi ...
- LeetCode——Fizz Buzz
LeetCode--Fizz Buzz Question Write a program that outputs the string representation of numbers from ...
- sql行列互换
出现这个结果: sql如下: end) as erjidu from a GROUP BY y;
- java处理图片base64编码的相互转换
转载自http://www.cnblogs.com/libra0920/p/5754356.html 直接上代码 import sun.misc.BASE64Decoder; import sun.m ...
- Spring Boot的核心
1.1.1. 入口类和@SpringBootApplication Spring Boot的项目一般都会有*Application的入口类,入口类中会有main方法,这是一个标准的Java应用程序 ...
- 获得Ztree选择的节点
$('#save').click(function(){ if($("#roleForm").form("validate")){ var treeObj = ...
- HDU 4725 建图
http://acm.hdu.edu.cn/showproblem.php?pid=4725 The Shortest Path in Nya Graph Time Limit: 2000/1000 ...
- QT延时方法
(转自:http://blog.sina.com.cn/s/blog_613cfe940100kacm.html) 1. void sleep(unsigned int msec){ QTime ...
- ubuntu下搭建hadoop平台
终于把单击模式跟伪分布式模式搭建起来了,记录于此. 1.SSH无密码验证配置 因为伪分布模式下DataNode和NameNode均是本身,所以必须配置SSH localhost的无密码验证. 第一步, ...