项目中需要用到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的更多相关文章

  1. Net Core动态加载webservice/WCF

    1.动态加载的目的 前端时间和顺丰对接了个项目(PS:顺丰的开发对外能力真的是掉粉),用的webservice 测试时用的无固定IP访问,正式版需要固定IP访问,我的理解是web服务都是全网络可以访问 ...

  2. Silverlight实用窍门系列:2.Silverlight动态加载外部XML指定地址的WebService---(动态加载外部XML文件中指定的WebService地址)【附带实例源码】

    接上节所讲的,Silverlight可以加载外部的XML文件里面的内容,那么我们可不可以在外部XML里面配置一个WebService地址,并且以此加载这个地址来动态加载WebService呢?这样子就 ...

  3. js动态加载css和js

    之前写了一个工具类点此链接里面含有这段代码,感觉用处挺多,特意提出来 var loadUtil = { /* * 方法说明:[动态加载js文件css文件] * 使用方法:loadUtil.loadjs ...

  4. geotrellis使用(二十三)动态加载时间序列数据

    目录 前言 实现方法 总结 一.前言        今天要介绍的绝对是华丽的干货.比如我们从互联网上下载到了一系列(每天或者月平均等)的MODIS数据,我们怎么能够对比同一区域不同时间的数据情况,采用 ...

  5. Ext JS 如何动态加载JavaScript创建窗体

    JavaScript不需要编译即可运行,这让JavaScript构建的应用程序可以变得很灵活.我们可以根据需要动态从服务器加载JavaScript脚本来创建和控制UI来与用户交互.下面结合Ext JS ...

  6. Ext动态加载Toolbar

    在使用Ext的GridPanel时候,有时候需要面板不用重新加载而去更新Store或者Toolbar,Store的方法有很多,例如官方api给我们提供的Store.load(),Store.reLoa ...

  7. Android动态加载框架汇总

    几种动态加载的比较 1.Tinker 用途:热修复 GitHub地址:https://github.com/Tencent/tinker/ 使用:http://www.jianshu.com/p/f6 ...

  8. 为不同分辨率单独做样式文件,在页面头部用js判断分辨率后动态加载定义好的样式文件

    为不同分辨率单独做样式文件,在页面头部用js判断分辨率后动态加载定义好的样式文件.样式文件命名格式如:forms[_屏幕宽度].css,样式文件中只需重新定义文本框和下拉框的宽度即可. 在包含的头文件 ...

  9. html中的图像动态加载问题

    首先要说明下文档加载完成是什么概念 一个页面http请求访问时,浏览器会将它的html文件内容请求到本地解析,从窗口打开时开始解析这个document,页面初始的html结构和里面的文字等内容加载完成 ...

随机推荐

  1. 【转】和菜鸟一起学linux之DBUS基础学习记录

    [原文] D-Bus三层架构 D-Bus是一个为应用程序间通信的消息总线系统, 用于进程之间的通信.它是个3层架构的IPC 系统,包括: 1.函数库libdbus ,用于两个应用程序互相联系和交互消息 ...

  2. Android -- listview的使用, Inflater打气筒创建View对象,三种数据Adapter

    1. 代码示例,( 数据库来源上篇的数据) MainActivity.java public class MainActivity extends Activity { private ListVie ...

  3. centos 安装jdk/resin/mysql

    一.安装JDK 1.判断是否安装 java -version 我的计算机上使用java -version命令,内容如下: java version "1.7.0_45"OpenJD ...

  4. SpringBoot实现文件上传功能

    新建maven项目,pom文件: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="htt ...

  5. 利用$http获取在服务器的json数据

    以下是存储在web服务器上的 JSON 文件: http://www.runoob.com/try/angularjs/data/Customers_JSON.php { "records& ...

  6. mvvm2

    1:设计模式 在MVP模式中,为了让UI层能够从逻辑层上分离下来,设计师们在UI层与逻辑层之间加了一层interface.无论是UI开发人员还是数据开发人员,都要尊重这个契约.按照它进行设计和开发.这 ...

  7. android开发环境:使用Android Studio搭建Android集成开发环境(图文教程)

    开发环境情况: 物理机版本:Win 7旗舰版(64位) Java SDK版本:jdk1.8.0_25(64位) Android SDK版本:Android 7.1(API 25) Android St ...

  8. spring boot配置德鲁伊

    1.引入相关依赖,全部依赖是上一篇spring boot+mybatis依赖的基础上,再加上下边的依赖,如下: <!-- Druid数据库连接池组件 --> <dependency& ...

  9. CentOS7 安装ifconfig

    As we all know, “ifconfig” command is used to configure a network interfaces in GNU/Linux systems. I ...

  10. MS SQL GUID

    (转自:http://blog.csdn.net/maonongwu/article/details/6327093) GUID介绍 GUID(Global unique identifier)全局唯 ...