内部通信服务Factory(WCF)
WCF,很好,却又麻烦,很多时候不想用WCF的原因就是:用这个真麻烦...
麻烦的地方,比如:
- 一堆一堆的服务配置,散落在一个一个的folder下,更新系统时容易出错
- 客户端除了要知道WCF Contract外,还要知道服务Provider所在位置
所以想了个办法来简化这些,主要思路是:
- 加入Internal Communication Service,简称ICS。用来插入自定义的中间层
- 编写一个Service Locator Service,用来将WCF服务提供者信息抽取统一保存,如:url, endpoint类型,做到wcf服务提供者位置无关性
完成后,WCF客户端(包括WCF服务内部调用了其他WCF服务的服务...)调用代码会变成如下方式:
//不支持事务的调用方式
IUser userSrv = ICSFactory.Create<IUser>();
var result = userSrv.GetUserName("", "", "");
ICSFactory.Close(userSrv); //支持事务的调用方式
string result = string.Empty;
using (TransactionScope ts = new TransactionScope())
{
IUser userSrv = ICSFactory.Create<IUser>();
IAdmin adminSrv = ICSFactory.Create<IAdmin>(); result = userSrv.GetUserName("", "", "");
result = adminSrv.CheckPermission().ToString(); ts.Complete(); ICSFactory.Close(userSrv);
ICSFactory.Close(adminSrv);
}
WCF客户端的配置信息去哪了呢? A:在appSetting中,有个key,用来表示服务配置信息文件所在路径,如:\\fs\root\a2d.service.config,配置文件如下:
<?xml version="1.0" encoding="utf-8" ?>
<A2D>
<ServiceLocator>
<Service ContractNamespace="DEsbInterface" Contract="IUser">
<Url EndpointType="Tcp">net.tcp://192.168.1.100:9999/usersrv</Url>
</Service>
<Service ContractNamespace="DEsbInterface" Contract="IAdmin">
<Url EndpointType="Tcp">net.tcp://192.168.1.100:9998/adminsrv</Url>
</Service>
</ServiceLocator>
</A2D>
如果调用WCF服务的客户端只有一个程序,就没多大用了,但是如果有很多客户端程序,那就有用了,如下场景:
4台server都作为客户端进行WCF服务的调用
ICS原理:
在本例中,ICS其实就是ICSFactory,用来建立WCF服务代理,通过代码方式加入binding、address、transaction信息,底层调用的是ChannelFactory来建立通信,代码如下:
public class ICSFactory
{
/// <summary>
/// 创建WCF服务代理对象
/// </summary>
/// <typeparam name="T">WCF的Contract类型</typeparam>
/// <returns></returns>
public static T Create<T>()
{
string contractNamespace = typeof(T).Namespace;
string contract = typeof(T).Name; //根据WCF Contract信息找到相应的位置信息
Location location = ServiceLocator.Locate(contractNamespace, contract); //生成绑定信息
NetTcpBinding binding = new NetTcpBinding();
binding.ReceiveTimeout = new TimeSpan(, , );
binding.Security.Mode = SecurityMode.None;
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None; //事务设置
binding.TransactionFlow = true;
binding.TransactionProtocol = TransactionProtocol.OleTransactions; //地址信息
EndpointAddress address = new EndpointAddress(location.Url); //建立信道
T broker=ChannelFactory<T>.CreateChannel(binding, address); //返回代理对象
return broker;
} /// <summary>
/// Dispose代理对象
/// </summary>
/// <param name="broker"></param>
public static void Close(object broker)
{
if (broker == null)
return; IDisposable disposable = broker as IDisposable;
if (disposable == null)
return; disposable.Dispose();
}
}
Service Locator Service原理:
也就是ServiceLocator.Locate函数。
程序启动时会根据配置读取config文件的xml到内存对象中:Service、Url。具体代码略。
Locate函数的代码如下:
/// <summary>
/// 根据Contract的命名空间及Contract名找到服务的真实地址信息
/// </summary>
/// <param name="contractNamespace"></param>
/// <param name="contract"></param>
/// <returns></returns>
public static Location Locate(string contractNamespace, string contract)
{
Service srv=null; string key = string.Format("{0}.{1}", contractNamespace, contract);
if (!serviceCache.ContainsKey(key))
{
srv = FindService(contractNamespace, contract, srv);
serviceCache[key] = srv;
}
else
{
srv=serviceCache[key];
}
if(srv.Urls==null||srv.Urls.Count==)
throw new Exception(string.Format("Service' url not found [{0}.{1}]", contractNamespace, contract)); Url url=srv.Urls.First(); Location location = new Location();
location.EndpointType = url.EndpointType;
location.Url = url.ReferenceUrl;return location;
} private static Service FindService(string contractNamespace, string contract, Service srv)
{
List<Service> matchedServices = LocatorServiceConfiguration.Services.Where(t =>
t.Contract.CompareTo(contract) ==
&&
t.ContractNamespace.CompareTo(contractNamespace) ==
).ToList(); if (matchedServices == null || matchedServices.Count == )
throw new Exception(string.Format("Service not found [{0}.{1}]", contractNamespace, contract)); srv = matchedServices.First();
return srv;
}
内部通信服务Factory(WCF)的更多相关文章
- autofac 注入普通服务和WCF服务
using Autofac;using Autofac.Builder;using Autofac.Core; //实现Autofac扩展 public static AutofacRegisterW ...
- 从开发的角度比较 ASP.NET Web 服务与 WCF
Windows Communication Foundation (WCF) 具有一个 ASP.NET 兼容模式选项,用户使用此选项可以对 WCF 应用程序进行编程和配置,使其像 ASP.NET We ...
- WCF开发实战系列四:使用Windows服务发布WCF服务
WCF开发实战系列四:使用Windows服务发布WCF服务 (原创:灰灰虫的家http://hi.baidu.com/grayworm) 上一篇文章中我们通过编写的控制台程序或WinForm程序来为本 ...
- Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务、WCF消息头添加安全验证Token
原文:Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务.WCF消息头添加安全验证Token 为什么选择wcf? 因为好像wcf和wpf就是哥俩,,, 为什么选择异步 ...
- C#.NET 操作Windows服务承载WCF
Windows服务的制作.安装可以参考这篇: C#.NET 操作Windows服务(安装.卸载) - runliuv - 博客园 (cnblogs.com) 本篇会在这个解决方案基础上,继续修改. 一 ...
- IOS调用WCF服务,WCF服务器进行上传图片
1.IOS端采用post方式请求服务器端的url地址 如:http://192.168.0.12:50000/serverce1.svc/upload IOS端的代码采用base64位编码的方式传值给 ...
- WCF服务与WCF数据服务的区别
问: Hi, I am newbie to wcf programming and a little bit confused between WCF Service and WCF Data Se ...
- 重温WCF之构建一个简单的WCF(一)(2)通过Windows Service寄宿服务和WCF中实现操作重载
参考地址:http://www.cnblogs.com/zhili/p/4039111.html 一.如何在Windows Services中寄宿WCF服务 第一步:创建Windows 服务项目,具体 ...
- 创建服务factory和service方法的区别
factory方法返回的是对象,json或数组,也可以返回字符串类型的数据,但service方法只能返回数据或对象 创建服务有3种方法 $provide.provider('服务名',function ...
随机推荐
- C++中new和malloc的区别
原文:http://blog.163.com/ji_wei8888/blog/static/4868044620117361747282/ 1.new 是c++中的操作符,malloc是c 中的一个函 ...
- 正则表达式匹配完整img标签php实现
处理html富文本的时候,碰到批量处理img标签,要把img标签格式化,并且去除不用的代码,class,各种data-等,首先想到使用正则匹配,然后处理匹配到的img标签和参数,经过一番尝试终于搞定了 ...
- iOS多线程编程之NSOperation和NSOperationQueue的使用(转自容芳志专栏)
转自由http://blog.csdn.net/totogo2010/ 使用 NSOperation的方式有两种, 一种是用定义好的两个子类: NSInvocationOperation 和 NSBl ...
- SQL中Group By 的使用
1.概述 “Group By”从字面意义上理解就是根据“By”指定的规则对数据进行分组,所谓的分组就是将一个“数据集”划分成若干个“小区域”,然后针对若干个“小区域”进行数据处理. 2.原始表 3.简 ...
- Remoting首次用时偏长问题
先说我遇到的问题,我需要访问多个服务器的一个相同的Remoting方法,根据方法返回的结果决定优先使用某个服务器. var _remoteFacade = Activator.GetObject(ty ...
- [C++]项目中的代码注释规范(整理)
原文:http://blog.csdn.net/pleasecallmewhy/article/details/8658795 1 源文件头部注释 列出:版权.作者.编写日期和描述. 每行不要超过80 ...
- linux tcp协议定时器
1 连接建立定时器:75秒 2 保活定时器:2小时又10分钟 3 重传定时器:根据RTT计算 4 2MSL定时器:最大报文段存活时间 5 持续定时器
- EF(Entity Framework)多对多关系下用LINQ实现"NOT IN"查询
这是今天在实际开发中遇到的一个问题,需求是查询未分类的博文列表(未加入任何分类的博文),之前是通过存储过程实现的,今天用EF实现了,在这篇博文中记录一下. 博文的实体类BlogPost是这样定义的: ...
- nodeJs开发app.js解析
在 node.js 中模块分为核心模块和文件模块两种,核心模块是通过 require('xxxx') 导入的,文件模块是以 require('/xxxx') 或 require('./xxxx').r ...
- C# VS JAVA 差异 (未完待续)
1. 静态构造函数 C#中有静态构造函数, Java中没有静态构造函数.其实Java中有一个类似静态构造函数的东东,称作静态初始化,或者静态代码块,可以通过这样的代码实现相同的功能: 但是Java中静 ...