c#wcf的wcf createchannellfactory<t>是经过动态编译实现的么

君,已阅读到文档的结尾了呢~~
C# WCF入门学习
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
C# WCF入门学习
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口您所在的位置: &
分享基于EF+WCF的通用三层架构及解析
分享基于EF+WCF的通用三层架构及解析
本项目结合EF 4.3及WCF实现了经典三层架构,各层面向接口,WCF实现SOA,Repository封装调用,在此基础上实现了WCFContext,动态服务调用及一个分页的实例。
本项目结合EF 4.3及WCF实现了经典三层架构,各层面向接口,WCF实现SOA,Repository封装调用,在此基础上实现了WCFContext,动态服务调用及一个分页的实例。
1. 项目架构图:
498)this.width=498;' onmousewheel = 'javascript:return big(this)' border="0" alt="" width="700" height="520" src="/files/uploadimg/2120.jpg" />&
2. 项目解决方案:
498)this.width=498;' onmousewheel = 'javascript:return big(this)' border="0" alt="" src="/files/uploadimg/2121.jpg" />
在传统的三层架构上增加了WcfService(服务端),WcfClientProxy(客户端服务调用),及WcfExtension(一些扩展)
3. Wcf Service的实现:
498)this.width=498;' onmousewheel = 'javascript:return big(this)' border="0" alt="" src="/files/uploadimg/2122.jpg" />
工厂实现了RemoteServiceFactory(用于远程调用)和RefServiceFactory(本地引用调用服务层)生成客户端代理,都需要实现IServiceFactory的&IService CreateService();&
RemoteServiceFactory通过ChannelFactory动态产生客户端代理类IService,并将此对象进行缓存
WCFExtension实现了WCFContext,可传输用户登陆或IP上下文信息,以及拦截方法写Log的机制,具体可以参考
3. 数据层Repository的实现:
498)this.width=498;' onmousewheel = 'javascript:return big(this)' border="0" alt="" src="/files/uploadimg/2123.jpg" />&
通过用来访问领域对象的一个类似集合的接口,在领域与数据映射层之间进行协调,将领域模型从客户代码和数据映射层之间解耦出来,具体实现代码:
View&Code& &&public&class&DaoBase&:&IRepository,&IDisposable &&&&&&{ &&&&&&&&&&public&DbContext& && &&&&&&&&&&public&DaoBase() &&&&&&&&&&{ &&&&&&&&&&&&&&this.context&=&new&EasyEF.DAL.DbContext(); &&&&&&&&&&} && &&&&&&&&&&public&T&Update&T&(T&entity)&where&T&:&class&&&&&&&&&&{ &&&&&&&&&&&&&&var&set&=&context.Set&T&(); &&&&&&&&&&&&&&set.Attach(entity); &&&&&&&&&&&&&&context.Entry&T&(entity).State&=&EntityState.M &&&&&&&&&&&&&&context.SaveChanges(); && &&&&&&&&&&&&&&return& &&&&&&&&&&} && &&&&&&&&&&public&T&Insert&T&(T&entity)&where&T&:&class&&&&&&&&&&{ &&&&&&&&&&&&&&context.Set&T&().Add(entity); &&&&&&&&&&&&&&context.SaveChanges(); &&&&&&&&&&&&&&return& &&&&&&&&&&} && &&&&&&&&&&public&void&Delete&T&(T&entity)&where&T&:&class&&&&&&&&&&{ &&&&&&&&&&&&&&context.Entry&T&(entity).State&=&EntityState.D &&&&&&&&&&&&&&context.SaveChanges(); &&&&&&&&&&} && &&&&&&&&&&public&T&Find&T&(params&object[]&keyValues)&where&T&:&class&&&&&&&&&&{ &&&&&&&&&&&&&&return&context.Set&T&().Find(keyValues); &&&&&&&&&&} && &&&&&&&&&&public&List&T&&FindAll&T&(Expression&Func&T,&bool&&&conditions&=&null)&where&T&:&class&&&&&&&&&&{ &&&&&&&&&&&&&&if&(conditions&==&null) &&&&&&&&&&&&&&&&&&return&context.Set&T&().ToList(); &&&&&&&&&&&&&&else&&&&&&&&&&&&&&&&&&return&context.Set&T&().Where(conditions).ToList(); &&&&&&&&&&} && &&&&&&&&&&public&PagedList&T&&FindAllByPage&T,&S&(Expression&Func&T,&bool&&&conditions,&Expression&Func&T,&S&&&orderBy,&int&pageSize,&int&pageIndex)&where&T&:&class&&&&&&&&&&{ &&&&&&&&&&&&&&var&queryList&=&conditions&==&null&?&context.Set&T&()&:&context.Set&T&().Where(conditions)&as&IQueryable&T&; && &&&&&&&&&&&&&&return&queryList.OrderByDescending(orderBy).ToPagedList(pageIndex,&pageSize); &&&&&&&&&&} && &&&&&&&&&&public&void&Dispose() &&&&&&&&&&{ &&&&&&&&&&&&&&this.context.Dispose(); &&&&&&&&&&}&
4. 数据层基于Entity Framwork code First:
View&Code& &&public&class&DbContext&:&System.Data.Entity.DbContext &&&&&&{ &&&&&&&&&&public&DbContext() &&&&&&&&&&&&&&:&base(&MyDbContext&) &&&&&&&&&&{ &&&&&&&&&&&&&&this.Configuration.ProxyCreationEnabled&=&false; &&&&&&&&&&} &&&&&&&&&& &&&&&&&&&&public&DbSet&Category&&Categories&{&get;&set;&} &&&&&&&&&&public&DbSet&Product&&Products&{&get;&set;&} &&&&&&}&
Model Mapping
View&Code& &&[Table(&Product&)] &&&&&&public&partial&class&Product &&&&&&{ &&&&&&&&&&public&int&Id&{&&&} && &&&&&&&&&&[StringLength(50)] &&&&&&&&&&[Required(ErrorMessage&=&&名称不能为空&)] &&&&&&&&&&public&string&Name&{&&&} && &&&&&&&&&&public&int&Size&{&&&} && &&&&&&&&&&[StringLength(300)] &&&&&&&&&&public&string&PhotoUrl&{&&&} && &&&&&&&&&&public&DateTime&AddTime&{&&&} && &&&&&&&&&&public&int&CategoryId&{&&&} &&&&&&&&&&public&virtual&Category&Category&{&&&} &&&&&&}&
5. 提供了MVC调用服务端分页的实例:
MVC调用Wcf客户代理请求分页数据集合
public&ActionResult&Index(int&pageIndex&&=&1) &&&&&&&&&{ &&&&&&&&&&&&&var&products&=&this.Service.GetProducts(PageSize,&pageIndex); &&&&&&&&&&&&&return&View(products); &&&&&&&&&}&
MVC附加用户Context信息到服务端
protected&override&void&OnActionExecuting(ActionExecutingContext&filterContext) &&&&&&&&&&{ &&&&&&&&&&&&&&base.OnActionExecuting(filterContext); &&&&&&&&&&&&&&WCFContext.Current.Operater&=&new&Operater(){Name&=&&guozili&,Time&=&DateTime.Now,IP&=&Fetch.UserIp,}; &&&&&&&&&&}&
BLL取出Context信息并调用数据层
public&PagedList&Product&&GetProducts(int&pageSize,&int&pageIndex,&int&categoryId&=&0) &&&&&&&&&&{ &&&&&&&&&&&&&&&&&&&&&&&&&&&&var&context&=&WCFContext.Current.O &&&&&&&&&&&&&&return&this.dao.FindAllByPage&Product,&int&(p&=&&categoryId&==&0&?&true&:&p.CategoryId&==&categoryId,&p&=&&p.Id,&pageSize,&pageIndex); &&&&&&&&&&}&
DAL调用通用的Repository接口
public&PagedList&T&&FindAllByPage&T,&S&(Expression&Func&T,&bool&&&conditions,&Expression&Func&T,&S&&&orderBy,&int&pageSize,&int&pageIndex)&where&T&:&class&&&&&&&&&&{ &&&&&&&&&&&&&&var&queryList&=&conditions&==&null&?&context.Set&T&()&:&context.Set&T&().Where(conditions)&as&IQueryable&T&; && &&&&&&&&&&&&&&return&queryList.OrderByDescending(orderBy).ToPagedList(pageIndex,&pageSize); &&&&&&&&&&}&
6. 最后提供源码下
原文链接:【编辑推荐】【责任编辑: TEL:(010)】
关于&&&&&&的更多文章
这个架构是从我近期在做的一个项目中剥离出来的,这个项目由我从
随着云计算、物联网、大数据、移动互联网的大发展,你应该知道这些。
数据结构课程,貌似是大学计算机、网络、软件等专业的
JavaScript正凭借新型工具与功能提升以极度夸张的速度
国庆假期前的612,是不是有点折腾?网上的中秋国庆放
一个网站,无论视觉上多美观或者内容多丰富,如果它不能适应各种浏览情况并能面向尽可能广泛的用户群,那它就不算是真正成功的网
51CTO旗下网站wayfarer 的BLOG
用户名:wayfarer
文章数:117
评论数:72
访问量:150874
注册日期:
阅读量:5863
阅读量:12276
阅读量:414865
阅读量:1102365
[匿名]master:
51CTO推荐博文
《Programming WCF Services》翻译笔记之五
请求-应答(Request-Reply)操作
&除了NetPeerTcpBinding和NetMsmqBinding绑定,所有的绑定均支持请求-应答操作。&
单向操作没有返回值。单向操作不同于异步操作,虽然单向操作只是在发出调用的瞬间阻塞客户端,但如果发出多个单向调用,WCF会将这些调用放入队列。队列存 储调用的个数是有限的,一旦发出的调用个数超出了队列存储调用的设置值,则会发生阻塞现象,因为调用无法放入队列。当队列的请求出列后,产生阻塞的调用就 会放入队列,并解除对客户端的阻塞。
设置单向操作的方法是利用OperationContract特性的IsOneWay属性,例如:
[ServiceContract]
interface IMyContract
&& [OperationContract(IsOneWay = true)]
&& void MyMethod(& );
被设置为单向操作的方法不能包含返回值,即它的返回值只能为void,否则会抛出InvalidOperationException异常。
在 会话契约中虽然允许定义单向操作,但由于单向操作无法正确地维持状态,因而,单向操作的最佳适用场景是在单调服务或单例服务中。&如果在会话契约中定义了 单向操作,就必须保证单向操作是终止会话的最后一个操作(该操作必须遵循单向操作的规定,例如返回void类型值)。这可以通过分步操作来实现。&
单向操作如果抛出异常,则视其服务模型以及使用绑定的不同,会产生不同的结果。以下内容假定服务不会抛出FaultException异常或者它的子类。
BasicHttpBinding绑定
客户端不受影响
不包含可靠消息传输与安全的WSHttpBinding绑定
客户端不受影响
具有安全性的WSHttpBinding绑定
通道错误,客户端无法继续发出调用
不包含可靠消息传输的NetTcpBinding或NetNamedPipeBinding绑定
通道错误,客户端无法继续发出调用
具有可靠消息传输的WSHttpBinding绑定或NetTcpBinding绑定
客户端不受影响
如果是在会话服务中,则单向操作抛出的异常都会影响到客户端,只不过如果使用的绑定不相同,则抛出的异常会有所区别。
对于单例服务而言,无会话的单例服务与单调服务相似,具有会话的单例服务则与会话服务相似。
回调机制如图所示:
回调机制尤其适用于事件。在WCF中,BasicHttpBinding或WSHttpBinding绑定并不支持回调,因为它们不支持双向通信。 NetTcpBinding和NetNamedPipeBinding绑定以及WSDualHttpBinding绑定支持回调操作。
定义回调契约
一个服务契约最多只能包含一个回调契约。通过ServiceContract特性,可以指定回调契约:
interface ISomeCallbackContract
&& [OperationContract]
&& void OnCallback(& );
[ServiceContract(CallbackContract = typeof(ISomeCallbackContract))]
interface IMyContract
&& [OperationContract]
&& intDoSomething(& );
回调契约无须标记ServiceContract特性,但是在回调契约中必须为服务的操作标记OperationContract特性。
在导入回调契约的元数据中,回调契约以Callback结尾。为简便起见,我们在定义回调契约时,最好以Callback为后缀。
为了托管一个回调对象,客户端需要实例化回调对象,然后通过它创建一个上下文对象:
class MyCallback : IMyContractCallback
&& public void OnCallback(& )
IMyContractCallback callback = new MyCallback(& );
InstanceContext context = new InstanceContext(callback);
假定客户端的代理类为MyContractClient,则在客户端就可以通过上下文对象获得代理对象:
MyContractClient proxy = new MyContractClient(context);
注意,如果使用了回调契约,则客户端生成的代理类必须继承自DuplexClientBase&T&代理类,这是一个专门的支持双向通信的代理 类。注意,该类的构造函数参数既可以接收InstanceContext类型的上下文对象,也可以接收object类型的回调契约对象。
然而,如果是通过SvcUtil或Visual Studio 2005生成的代理,却不能使用接收object类型对象的构造函数,若要创建代理对象,我们必须先创建上下文对象,如前面的代码所示。
我们可以手动修改代理类,添加对它的支持,如下所示:
partial class MyContractClient : DuplexClientBase&IMyContract&,IMyContract
&& public MyContractClient(object callbackInstance) : base(callbackInstance)
&& //More constructors
&& public void DoSomething(& )
&&&& Channel.DoSomething(& );
class MyClient : IMyContractCallback,IDisposable
&& MyContractClient m_P
&& public void CallService(& )
&&&&& m_Proxy = new MyContractClient(this);
&&&&& m_Proxy.DoSomething(& );
&& public void OnCallback(& )
&& public void Dispose(& )
&&&&& m_Proxy.Close(& );
注意,上述的代码中直接由客户端实现了回调契约,这是一种比较常见的实现方式。
客户端通过回调传递给服务端的消息包含了回调契约终结点的引用。在服务端,可以通过OperationContext类的泛型方法GetCallbackChannel&T&()获得。如下所示:
ISomeCallbackContract callback = OperationContext.Current.GetCallbackChannel&ISomeCallbackContract&();
服务对回调的调用可能会产 生死锁。例如,当客户端执行服务操作时,向客户端发出的调用会阻塞服务端进程,以等待服务操作执行完毕。而在该服务操作中,又获得了回调契约对象的引用 (或者获得保存的回调契约副本),并执行回调操作。由于服务类被配置为单线程访问,则服务实例是与锁相关联的。如果回调对象也需要返回同一个锁的所有权, 简单的说,就是指当回调的应答消息也需要获得与服务实例关联的相同的锁时,就会导致死锁。因为此时服务线程已经被阻塞,服务操作正在等待回调操作执行完 毕,而回调操作却又在等待服务释放锁,自然会产生锁的争用。
解决死锁的办法有三个,一个是将服务配置为允许多线程访问,但这会增加服务开发者管理多线程的负担。第二个方案是将回调设置为重入(Reentrancy),如下所示:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class MyService : IMyContract
&& public void DoSomething(& )
&&&&& IMyContractCallback callback = OperationContext.Current.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& GetCallbackChannel&IMyContractCallback&(& );
&&&&& callback.OnCallback(& );
所谓&重入&,是指对同步域拥有独占访问权的线程A调用了同步域之外对象的方法,此时,另外的线程B若要访问该同步域,则线程A将释放对同步域的锁,允许线 程B进入。直到线程B执行完毕并释放对同步域的锁后,线程A将重新进入该同步域。配置回调为重入时,因为服务对象是与线程关联的,属于同步域的对象,而回 调对象则属于同步域之外的对象。由于服务被配置为重入,则服务调用回调引用时会释放锁。然后将回调返回给客户端,控制权则返回给服务,服务会重入并重新获 取锁。这样就解决了死锁的问题。
第三种方案则是将回调操作设置为单向操作。此时,回调调用不会产生应答消息,服务操作一旦执行了回调操作,就会继续执行,回调对象不会争用与服务实例关联的锁,从而解决了死锁问题。
interface IMyContractCallback
&& [OperationContract(IsOneWay = true)]
&& void OnCallback(& );
在使用回调对象时,需要考虑到客户端代理可能会被关闭,如果此时调用回调,就会引发一个ObjectDisposedException异常。&因此,对于 客户端而言,当它不再需要接收回调或者客户端应用程序已经关闭时,最好能够通知服务。&本书给出了解决这一问题的方法,就是为服务契约增加两个操作 Connect()与Disconnect()。其中,Disconnect()正是起到了通知服务的作用,它在客户端代理关闭的情况下,可以将当前的回 调对象引用从列表中移除。至于Connect()方法则是出于对称的目的而引入,但引入它还有一个好处是,它可以使得客户端能够多次地连接或断开。实现 Connect()与Disconnect()方法的代码如下:
单 调服务与单例服务非常适合使用这种方式维持回调对象引用。会话服务则没有必要。&但是,如果会话服务为了让其它宿主端或跨会话访问,而将它的回调引用保存 在某个全局变量中,就必须添加Disconnect()方法,以达到移除回调引用的目的,因为在调用Dispose()期间不能使用回调引用。&
DuplexClientBase&T&类并没有为回调契约提供类型安全性,也没有对服务契约与回调契约之间的约束关系进行验证。因此,本书还提供了DuplexClientBase&T,C&类,通过反射、泛型等技术对其提供类型安全。
与 ChannelFactory&T&类相似,WCF同样提供了DuplexChannelFactory&T&类,它被用于通过 编程方式设置双向代理。同样的,DuplexChannelFactory&T&类仍然缺乏对回调契约的类型安全。因此,本书提供了 DuplexChannelFactory&T,C&类,可以弥补DuplexChannelFactory&T&类的不足。
回调契约仍然具有继承的层级。书中讲述了很多,其实一言以蔽之,就是要求回调契约的层级与服务契约的层级保持一致。此外,服务自身还可以实现回调契约。
由 于使用WSDualHttpBinding绑定执行回调时,需要开通两个HTTP通道,一个用于服务,一个用于回调。通常,WCF为回调通道选择了默认的 80端口,但如果客户端运行了IIS,则可能会占用80端口,就会导致端口的冲突。实际上,我们可以为回调通道指定任何可用的端口,例如,我们可以通过配 置文件为客户端指定基地址。然而,我们指定的端口仍然可能会被占用,只是这种占用的可能性比80端口小。为了避免潜在的端口冲突,同时简化程序员的工作, 最好的办法是自动分配一个可用的端口。本书定义了WsDualProxyHelper静态辅助类,能够将客户端基地址设置为任意的可用端口。定义如下:
static List&IMyContractCallback& m_Callbacks = new List&IMyContractCallback&(& );
public void Connect(& )
&& IMyContractCallback callback = OperationContext.Current.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& GetCallbackChannel&IMyContractCallback&(& );
&& if(m_Callbacks.Contains(callback) == false)
&&&&& m_Callbacks.Add(callback);
public void Disconnect(& )
&& IMyContractCallback callback = OperationContext.Current.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& GetCallbackChannel&IMyContractCallback&(& );
&& if(m_Callbacks.Contains(callback) == true)
&&&&& m_Callbacks.Remove(callback);
&&&&& throw new InvalidOperationException(&Cannot find callback&);
WsDualProxyHelper类的使用如下所示:
class MyClient : IMyContractCallback
IMyContractCallback callback = new MyClient(& );
InstanceContext context = new InstanceContext(callback);
MyContractClient proxy = new MyContractClient(context);
WsDualProxyHelper.SetClientBaseAddress(proxy);
本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:┆阅读(0)┆评论(0)前面我们扩展了ServiceHost,这节我们将扩展ChannelFactory扩展2个类public class LChannelFactory&T& : ChannelFactory&T&
public class LDuplex&T& : DuplexChannelFactory&T&
由于DuplexChannelFactory&T&继承了ChannelFactory&T&本节我们以扩展DuplexChannelFactory&T&为例进行说明。当然,别担心,这两个类的扩展我们都会提供源。一个LDuplex&T& &#43; LChannelFactory&T&5.1 文件 App.config1)要真正讲扩展ChannelFactory之前,我还还是来了解下,我们ChannelFactory扩展操作了哪些参数。所以,与ServiceHost一样,先了解配置。2)这儿也是一个App.config在一定程度上,WCF是依赖于配置的,即便我们可以以编码的方式添加WCF运行参数。如图5.1.1所示。客户端配置非常简单,甚至连行为配置behaviorConfiguration也可为空。但此处我们为了完整的说明客户商端配置。我们采用图 5.1.2去解释客户端完整的配置。图5.1.1客户端配置5.2 完整的客户端 App.config客户端配置由三部分关键信息组成:Client : 含endpoint节点的客户端通信信息Bindings: 绑定参数。主要是TCP通信控制参数,为client中的endpoint信息服务。Behaviors: 行为。为client中的endpoint信息服务。还记不记得我们的的配置服务 – 绑定 – 行为客户 – 绑定 – 行为有了这样的对比,只是这儿从服务变成了客户。我们基本清楚了ChannelFactory要做一些什么工作。你可能猜测,这个ChannelFactory类是不是也得有一个protected virtual void ApplyConfiguration();
方法来对配置进行操作,而我们只需要重写ApplyConfiguration就可以了?你猜得没错。的确。ChannelFactory类有这样的方法存在:protected virtual void ApplyConfiguration(string configurationName);
不过,我们在ChannelFactory中的确要重写基类的这个方法,但还要重写另外一个方法:protected override ServiceEndpoint CreateDescription();
这是因为,可能有很多endpoint,我们需要将每一个endpoint信息加入到ServiceEndpoint中图5.2.1客户端完整配置现在。我们的问题清楚了。我们要重写CreateDescription方法,并加入client信息,dings信息与behaviors信息。这样我们将达成最初的设想。回过头来,看前面提到的public class LChannelFactory&T& : ChannelFactory&T&
public class LDuplex&T& : DuplexChannelFactory&T&
public class LChannelFactory&T& : ChannelFactory&T&
public class LDuplex&T& : DuplexChannelFactory&T&
你的想法是对了。这儿一个用来单向通信,DuplexChannelFactory则是双向通信的。在这节中,我们以DuplexChannelFactory为例说明如何重写CreateDescription这个方法。这儿比ServiceHost重写ApplyConfiguration稍复杂,因为CreateDescription内部有很多工作要做。1)重写CreateDescription 我们关心的是这个函数做了哪些工作?[1] 更改配置路径[2]添加endpoint信息[3]创建bindings与添加客户端行为/// &summary&
/// Override CreateDescription and applyConfiguration
/// &/summary&
/// &returns&&/returns&
protected override ServiceEndpoint CreateDescription()
// Set path!!!!!!!!!!!!!!!!
this.configpath = ConfigI
this.endpointCfgname = ServiceI
if (!CheckConfigExist(this.configpath))
return base.CreateDescription();
if (string.IsNullOrEmpty(this.endpointCfgname))
return base.CreateDescription();
lock (lockObj)
// Build service endpoint info
ServiceEndpoint servicep = new ServiceEndpoint(ContractDescription.GetContract(typeof(T)));
// Set serviceEndpoint name as config
//servicep.Name = this.endpointC
// Set user config
ExeConfigurationFileMap execfgMap = new ExeConfigurationFileMap();
execfgMap.ExeConfigFilename = this.
// Get config infomation
Configuration cfg = ConfigurationManager.OpenMappedExeConfiguration(execfgMap, ConfigurationUserLevel.None);
// Get all service model sections info
ServiceModelSectionGroup servicemodelSections = ServiceModelSectionGroup.GetSectionGroup(cfg);
// tmp servicep.Name
string tmpnameep =
// Get Endpoint element info
ChannelEndpointElement selectedep = GetEndpointElement(servicemodelSections,
servicep.Contract.ConfigurationName, out tmpnameep);
// Get completed servicep info
bool isAddAll = GetServicepCompletedInfo(servicep, servicemodelSections, selectedep);
// Set servicep.Name the right info
if (!string.IsNullOrEmpty(tmpnameforep)) servicep.Name =
this.epr = servicep.A
catch (Exception ex)
throw new Exception(&Error : CreateDescription exception ocurred! Apply user config failed!& + ex.ToString());
2)获取Endpoint信息/// &summary&
/// Get EndpointElement info
/// &/summary&
/// &param name=&servicemodelSections&&&/param&
/// &param name=&contractName&&&/param&
/// &param name=&epName&&&/param&
/// &returns&&/returns&
private ChannelEndpointElement GetEndpointElement(ServiceModelSectionGroup servicemodelSections,
string contractName, out string epName)
if (servicemodelSections == null)
if (string.IsNullOrEmpty(contractName))
ChannelEndpointElement epElement =
// Element flag
bool isExisted =
foreach (ChannelEndpointElement element in servicemodelSections.Client.Endpoints)
if (element.Contract == contractName &&
this.endpointCfgname == element.Name)
// Get element info
epElement =
// Get service name
epName = element.N
// Find successfully
isExisted =
if (!isExisted)
return epE
3)添加行为/// &summary&
/// &/summary&
/// &param name=&servicep&&&/param&
/// &param name=&servicemodelSections&&&/param&
/// &param name=&eplement&&&/param&
/// &returns&&/returns&
private bool GetServicepCompletedInfo(ServiceEndpoint servicep,
ServiceModelSectionGroup servicemodelSections, ChannelEndpointElement eplement)
if (eplement != null)
if (servicep.Binding == null)
servicep.Binding = CreateBinding(eplement.Binding, servicemodelSections);
if (servicep.Binding != null) this.isAddBinding =
if (servicep.Address == null)
servicep.Address = new EndpointAddress(eplement.Address, GetIdentityForVivitue(eplement.Identity), eplement.Headers.Headers);
if (servicep.Address != null) this.isAddAddr =
if (servicep.Behaviors.Count == 0 && eplement.BehaviorConfiguration != null)
bool isAdd =
isAdd = AddBehaviors(eplement.BehaviorConfiguration, servicep, servicemodelSections);
if (isAdd) this.isAddBehaviors =
if (this.isAddBinding && this.isAddAddr && this.isAddBehaviors)
/// &summary&
/// Add behaviors info
/// &/summary&
/// &param name=&behaviorCfg&&&/param&
/// &param name=&servicep&&&/param&
/// &param name=&modelGroup&&&/param&
/// &returns&&/returns&
private bool AddBehaviors(string behaviorCfg, ServiceEndpoint servicep, ServiceModelSectionGroup modelGroup)
if (string.IsNullOrEmpty(behaviorCfg))
if (servicep == null || modelGroup == null)
EndpointBehaviorElement behaviorElement = modelGroup.Behaviors.EndpointBehaviors[behaviorCfg];
for (int i = 0; i & behaviorElement.C i++)
BehaviorExtensionElement behaviorEx = behaviorE
object extention = behaviorEx.GetType().InvokeMember(&CreateBehavior&,
BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
behaviorEx,
if (extention == null)
servicep.Behaviors.Add((IEndpointBehavior)extention);
catch (Exception ex)
Console.Error.WriteLine(&Warning : Exception ocurred! Behaviors info added failed!
& + ex.ToString());
if (servicep.Behaviors.Count == 0)
4)创建bindings/// &summary&
/// Get Binding info
/// &/summary&
/// &param name=&element&&&/param&
/// &returns&&/returns&
private Binding GetBindingInfo(IBindingConfigurationElement element)
if (element == null)
if (element is CustomBindingElement) return new CustomBinding();
else if (element is BasicHttpBindingElement) return new BasicHttpBinding();
else if (element is NetMsmqBindingElement) return new NetMsmqBinding();
else if (element is NetNamedPipeBindingElement) return new NetMsmqBinding();
else if (element is NetTcpBindingElement) return new NetTcpBinding();
else if (element is WSDualHttpBindingElement) return new WSDualHttpBinding();
else if (element is WSHttpBindingElement) return new WSHttpBinding();
else if (element is WSFederationHttpBindingElement) return new WSFederationHttpBinding();
/// &summary&
/// Get binding info
/// &/summary&
/// &param name=&bindingName&&&/param&
/// &param name=&modelGroup&&&/param&
/// &returns&&/returns&
private Binding CreateBinding(string bindingName, ServiceModelSectionGroup modelGroup)
if (string.IsNullOrEmpty(bindingName))
if (modelGroup == null)
BindingCollectionElement bingdingElement = modelGroup.Bindings[bindingName];
if (bingdingElement.ConfiguredBindings.Count & 0)
IBindingConfigurationElement element = bingdingElement.ConfiguredBindings[0];
Binding binding = GetBindingInfo(element);
if (binding != null) element.ApplyConfiguration(binding);
catch (Exception ex)
Console.Error.WriteLine(&Attention : CreateBinding failed! & + ex.ToString());
5) 重写ApplyConfiguration/// &summary&
/// Override ApplyConfiguration
- Current doing nothing here
/// &/summary&
/// &param name=&configurationName&&&/param&
protected override void ApplyConfiguration(string configurationName)
//base.ApplyConfiguration
6) 获取证书信息这段代码后面我们讲 x.509证书时会说明。/// &summary&
/// Get identity
/// &/summary&
/// &param name=&element&&&/param&
/// &returns&&/returns&
private EndpointIdentity GetIdentityForVivitue(IdentityElement element)
if (element == null)
EndpointIdentity itentity =
//PropertyInformationCollection properties = element.ElementInformation.P
if (!string.IsNullOrEmpty(element.UserPrincipalName.Value))
return EndpointIdentity.CreateUpnIdentity(element.UserPrincipalName.Value);
else if (!string.IsNullOrEmpty(element.ServicePrincipalName.Value))
return EndpointIdentity.CreateSpnIdentity(element.ServicePrincipalName.Value);
else if (!string.IsNullOrEmpty(element.Dns.Value))
return EndpointIdentity.CreateDnsIdentity(element.Dns.Value);
else if (!string.IsNullOrEmpty(element.Rsa.Value))
return EndpointIdentity.CreateRsaIdentity(element.Rsa.Value);
else if (!string.IsNullOrEmpty(element.Certificate.EncodedValue))
X509Certificate2Collection supportCerfificates = new X509Certificate2Collection();
supportCerfificates.Import(Convert.FromBase64String(element.Certificate.EncodedValue));
if (supportCerfificates.Count == 0)
throw new InvalidOperationException(&Error : Unable to load certificate identity!&);
X509Certificate2 primaryCertificate = supportCerfificates[0];
supportCerfificates.RemoveAt(0);
return EndpointIdentity.CreateX509CertificateIdentity(primaryCertificate, supportCerfificates);
.3 关于LWCF为了让创建WCF客户端更清单。我们创建了LWCF来封装LDuplex与LChannelFactory1)服建WCF客户端通道/// &summary&
/// &/summary&
public void ConnectServer()
// Check config and service fullname!
CheckValidityAndThrowException();
// Clear last time record
this.linkElapsedTime = 0;
int beginTime = SysInfo.TickC
if (!linkStatus)
channelFactory = GetChannelInstance(this.wcfType);
if (channelFactory.State == CommunicationState.Created)
Instance = channelFactory.CreateChannel();
if (channelFactory.State == CommunicationState.Opened)
linkStatus =
linkStatus =
catch (Exception e)
linkStatus =
throw new Exception(e.);
// Get link time
this.linkElapsedTime = SysInfo.TickCount - beginT
2)获取ChannelFactory&T&实例/// &summary&
/// Get channel instance according WCFClientType
/// &/summary&
/// &param name=&type&&WCFClientType&/param&
/// &returns&&/returns&
private ChannelFactory&T& GetChannelInstance(WCFClientType type)
WCFClientType wtype =
ChannelFactory&T& channel =
switch (wtype)
case WCFClientType.Single:
channel = CreateLChannelFactory();
case WCFClientType.Duplex:
channel = CreateDuplexChannel();
case WCFClientType.Default:
channel = CreateComchannel();
channel = CreateComchannel();
catch (Exception ex)
Innerlig.Error(dclringType, &GetChannelInstance failed!&, ex);
3)获取WCF客户端实例/// &summary&
/// Get client instance
/// &/summary&
/// &returns&&/returns&
public T GetInstance()
return interfaceI
好了。到目前为止我们研究了WCF的配置文件,做了大量工作。完成了对ServiceHost的扩展与对ChannelFactory的扩展。形成了我们自己最终用的两个类:public class LWCF&T&
public class LServiceHost : ServiceHost
接下来,我们将用这两个类来升级我们的Lig服务。让Lig变成一个更加完美的版本。。。。。。。本节下载:————————————————————————————————————————————————————————————————————————————————————————————————图5.1.2中的的行为配置我们在后面讲x.509安全证书时会说到这段有用的客户端配置
behaviorConfiguration=&IgoreSvcCertValidation&
&behaviors&
&endpointBehaviors&
&behavior name=&IgoreSvcCertValidation&&
&clientCredentials&
&serviceCertificate&
&authentication certificateValidationMode=&None&/&
&/serviceCertificate&
&/clientCredentials&
&/behavior&
&/endpointBehaviors&
&/behaviors&

我要回帖

更多关于 wcf factory 的文章

 

随机推荐