热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

艾伟深入解析:WCFBinding模型中的绑定元素详解

本文深入解析了WCFBinding模型中的绑定元素,详细介绍了信道、信道管理器、信道监听器和信道工厂的概念与作用。从对象创建的角度来看,信道管理器负责信道的生成。具体而言,客户端的信道通过信道工厂进行实例化,而服务端则通过信道监听器来接收请求。文章还探讨了这些组件之间的交互机制及其在WCF通信中的重要性。

在上面的内容中,先后介绍了信道、信道管理器、信道监听器和信道工厂。从对象的创建来讲,信道管理器是信道的创建者。说的再具体点,客户端的信道通过信道工厂创建,服务端的信道通过信道监听器创建。但是信道工厂和信道监听器又是如果被创建出来的呢?

我们在一开始就已经说过,作为终结点三要素的绑定对象实现了所有的通信细节,并且通过创建信道栈实现了消息的传递。从这一点来说,绑定对象无疑是信道层所有通信对象的最终缔造者,所以信道工厂和信道监听器最终的创建都是靠绑定对象实现的。关于这个创建过程又和另一个重要的对象密切相关,那就是绑定元素。

1. 绑定元素(Binding Element)

绑定元素,顾名思义就是构成一个绑定对象的元素。绑定对象最根本的目的就是创建信道栈,借此实现对消息的传输、编码和基于消息交换的其他功能,比如安全、可靠传输、事务流转等等。组成信道栈的单个信道对象基于对某项单一功能的实现,在不同环境中,我们需要根据具体的需要创建相应的信道,并根据一定的顺序把这些信道组成一个完整的信道栈。对于绑定对象来说,如何实现这种灵活、自由的信道常创建方式,这得益于基于绑定元素的设计模式。

1.1. 关于绑定元素

从结构的角度讲,一个绑定对象有一系列绑定元素组成,每个绑定元素负责创建相应的信道。所以绑定元素几何的构成以及它们之间的先后顺序,决定了最终生成的信道栈中的信道组成已经它们位于栈中的先后顺序。WCF之所以在设计的时候将绑定和绑定元素分离开发,是基于灵活性、可扩展性考虑的。

在介绍信道和信道栈的时候我们说过,我们不可能、也不应该创建一个万能的信道能够提供消息交换中的所有的功能,所以我们让一个信道只承载某个单一的功能,比如传输信道专注于网络传输,消息编码信到专注于消息的编码,WCF还定义了一一系列的信道,他们分别关注与安全、可靠传输和事务流转等等。这种信道组合的设计方式使得我们可以根据具体的需求来定制我们将要创建的信道栈,让它只具有我们必须的功能,而去除不必要的功能。

同理,我们可以根据具体实际需求,将必要的绑定元素进行有序的组合,从而创建最能适合具体场景的绑定对象。由于信道可以分为必须的传输信道、消息编码信道和可选的基于某种WS-*协议实现的协议信道,与之相对地,我们的绑定元素可以分为传输绑定元素、消息编码绑定元素和协议绑定元素。

由于信道的实际创建者是信道管理器(信道工厂和信道监听器),所以绑定元素只需要实现对信道管理器的创建,而最终实现对具体信道的创建。所以绑定元素的最根本的功能就是实现对信道监听器和信道工厂的创建。这可以从所有绑定元素的基类, System.ServiceModel.Channels.BindingElement的定义上看出来:

public abstract class BindingElement
{// Methodsprotected BindingElement();protected BindingElement(BindingElement elementToBeCloned);public virtual IChannelFactory BuildChannelFactory(BindingContext context);public virtual IChannelListener BuildChannelListener(BindingContext context) where TChannel : class, IChannel;public virtual bool CanBuildChannelFactory(BindingContext context);public virtual bool CanBuildChannelListener(BindingContext context) where TChannel : class, IChannel;public abstract BindingElement Clone();public abstract T GetProperty(BindingContext context) where T : class;
}

 

BindingElement的核心方法成员有两个:BuildChannelListener和BuildChannelFactory和CanBuildChannelListener

1.2. 案例演示:如何自定义绑定元素

接下来,我们通过一个案例来演示如果自定义一个绑定元素。通过该绑定元素来创建我们在上面一个案例中创建的两个自定义信道管理器:SimpleChannelFactory和SimpleChannelListener。按照上面的命名方式,我们把这个自定义绑定元素命名为:SimpleBindingElement,下面是整个SimpleBindingElement的定义:

public class SimpleBindingElement : BindingElement
{public SimpleBindingElement(){PrintHelper.Print(this, "SimpleBindingElement");}public override BindingElement Clone(){PrintHelper.Print(this, "Clone");return new SimpleBindingElement();}public override T GetProperty(BindingContext context){PrintHelper.Print(this, string.Format("GetProperty<{0}>", typeof(T).Name));return context.GetInnerProperty();}public override IChannelFactory BuildChannelFactory(BindingContext context){PrintHelper.Print(this, "BuildChannelFactory");return new SimpleChannelFactory(context) as IChannelFactory;}public override IChannelListener BuildChannelListener(BindingContext context){PrintHelper.Print(this, "BuildChannelListener");return new SimpleChannelListener(context) as IChannelListener;}
}

SimpleBindingElement直接继承自抽象的基类BindingElement&#xff0c;对SimpleChannelFactory和SimpleChannelListener的创建分别实现在两个被重写的方法中&#xff1a;BuildChannelFactory和BuildChannelListener中。此外还重写了两个额外的方法&#xff1a;Clone和GetProperty&#xff0c;前者用于克隆一个新的绑定元素&#xff0c;后一个和定义在信道、信道管理器的同名方法一样&#xff0c;用于获取基于某种类型的属性。

2. 绑定揭秘

前面我们一直在谈论信道、信道管理器、信道监听器、信道工厂和绑定元素&#xff0c;现在我们才进体本章的主题。不过由于前面的铺垫已经很足了&#xff0c;绑定本身反而没有太多可大书特书了。如果从结构上给绑定下个定义&#xff0c;那么我的定义很简单&#xff1a;“绑定是绑定元素的有序集合”。

2.1. 绑定是绑定元素的有序集合

由于绑定的终极目标是实现对信道栈的创建&#xff0c;而对于一个信道栈来说&#xff0c;信道的构成和次序决定着该信道栈在最终消息通信中的特性与能力&#xff0c;而绑定元素有决定着信道的创建&#xff0c;所以绑定对象本身的特性与能力由构成它的所有绑定元素以及这些绑定元素之间的先后次序决定。

正因为如此&#xff0c;当我们需要判断某一个绑定类型是否支持某种特性的时候&#xff0c;可以通过查看该绑定是否具有与此特性相关的绑定元素。比如&#xff0c;我们要判断某种绑定是否支持某种类型的传输协议&#xff0c;只需要看看构成该绑定的传输绑定元素就可以了&#xff0c;WsHttpBinding的传输绑定元素是HttpTransportBindingElement&#xff0c;所以 只能支持基于HTTP或者HTTPS的传输协议&#xff1b;如果需要确定某种类型的绑定是否支持事务的流转&#xff0c;只需要查看该绑定的绑定元素集合中是否包含TransactionFlowBindingElement就可以了。

在WCF中&#xff0c;所有的绑定都直接或者间接继承自抽象基类&#xff1a;System.ServiceModel.Channels.Binding&#xff0c;我们现在来简单地分析一下这个基类。Binding实现了接口IDefaultCommunicationTimeouts。

public abstract class Binding : IDefaultCommunicationTimeouts
{public TimeSpan OpenTimeout { get; set; } public TimeSpan CloseTimeout { get; set; } public TimeSpan SendTimeout { get; set; }public TimeSpan ReceiveTimeout { get; set; }
}

 

四个默认的超时时限可以通过编程的方式显式指定&#xff0c;也可以通过配置的方式进行设置。他们的默认值分别为&#xff1a;OpenTimeout和CloseTimeout为1分钟&#xff0c;而SendTimeout和ReceiveTimeout为10分钟。

对于Binding&#xff0c;最为重要的就是如果构建组成该绑定对象的所有绑定元素集合。基于绑定元素的创建&#xff0c;通过抽象方法CreateBindingElements实现&#xff0c;所有具体的绑定类型均需要实现该方法。

public abstract class Binding : IDefaultCommunicationTimeouts
{ ... ...public abstract BindingElementCollection CreateBindingElements();
}

由于信道管理器栈创建相应的信道栈&#xff0c;而绑定创建信道管理器栈&#xff0c;因此在Binding中定义了一系列BuildChannelFactory和BuildChannelListener方法重载&#xff0c;用于创建信道工厂栈和信道监听器栈。此外&#xff0c;和BindingElement一样&#xff0c;CanBuildChannelFactory和CanBuildChannelListener用于检测绑定对象创建信道工厂和信道监听器的能力&#xff1a;

public abstract class Binding: IDefaultCommunicationTimeouts
{...public IChannelFactory BuildChannelFactory(params object[] parameters);public virtual IChannelFactory BuildChannelFactory(BindingParameterCollection parameters);public virtual IChannelListener BuildChannelListener(params object[] parameters) where TChannel : class, IChannel;public virtual IChannelListener BuildChannelListener(BindingParameterCollection parameters) where TChannel : class, IChannel;public virtual IChannelListener BuildChannelListener(Uri listenUriBaseAddress, params object[] parameters) where TChannel : class, IChannel;public virtual IChannelListener BuildChannelListener(Uri listenUriBaseAddress, BindingParameterCollection parameters) where TChannel : class, IChannel;public virtual IChannelListener BuildChannelListener(Uri listenUriBaseAddress, string listenUriRelativeAddress, params object[] parameters) where TChannel : class, IChannel;public virtual IChannelListener BuildChannelListener(Uri listenUriBaseAddress, string listenUriRelativeAddress, BindingParameterCollection parameters) where TChannel : class, IChannel;public virtual IChannelListener BuildChannelListener(Uri listenUriBaseAddress, string listenUriRelativeAddress, ListenUriMode listenUriMode, params object[] parameters) where TChannel : class, IChannel;public virtual IChannelListener BuildChannelListener(Uri listenUriBaseAddress, string listenUriRelativeAddress, ListenUriMode listenUriMode, BindingParameterCollection parameters) where TChannel : class, IChannel;public virtual bool CanBuildChannelFactory(BindingParameterCollection parameters);public bool CanBuildChannelFactory(params object[] parameters);public bool CanBuildChannelListener(params object[] parameters) where TChannel : class, IChannel;public virtual bool CanBuildChannelListener(BindingParameterCollection parameters) where TChannel : class, IChannel;
}

2.2. 案例演示&#xff1a;如何创建自定义绑定

在上一个案例演示中&#xff0c;我们创建了自定义的绑定元素&#xff1a;SimpleBindingElement&#xff0c;在案例中我们来真正使用绑定元素&#xff0c;为此我们创建一个直接继承自Binding的自定义绑定。为了简单起见&#xff0c;对于我们自定义的绑定&#xff0c;他仅仅包含三个必须的绑定元素&#xff1a;传输绑定元素和消息编码绑定元素&#xff0c;外加我们自定义的绑定元素。对于传输&#xff0c;我们采用基于HTTP协议的HttpTransportBindingElement&#xff0c;而对应消息编码&#xff0c;则采用基于文本编码方式的TextMessageEncodingBindingElement。我们索性将我们自定义的绑定命名为SimpleBinding&#xff0c;下面是SimpleBinding的定义&#xff1a;

namespace Artech.CustomChannels
{public class SimpleBinding : Binding{private string _scheme;private TransportBindingElement _transportBindingElement &#61; new HttpTransportBindingElement();private MessageEncodingBindingElement _messageEncodingBindingElement &#61; new TextMessageEncodingBindingElement();private SimpleBindingElement _SimpleBindingElement &#61; new SimpleBindingElement();public override BindingElementCollection CreateBindingElements(){BindingElementCollection elemens &#61; new BindingElementCollection();elemens.Add(this._SimpleBindingElement);elemens.Add(this._messageEncodingBindingElement);elemens.Add(this._transportBindingElement);return elemens.Clone();}public override string Scheme{get{return this._transportBindingElement.Scheme;}}}
}

对于整个SimpleBinding的定义&#xff0c;从形式上看显得异常的简单&#xff0c;仅仅是实现了定义在Binding中的抽象方法CreateBindingElements。在CreateBindingElements方法中&#xff0c;返回一个表示绑定元素集合的BindingElementCollection对象&#xff0c;在该集合中&#xff0c;包含三种类型的绑定元素&#xff0c;有上到下的顺序分别为&#xff1a;SimpleBindingElement、MessageEncodingBindingElement和HttpTransportBindingElement。此外重写了Scheme只读属性&#xff0c;它返回HttpTransportBindingElement的scheme&#xff1a;http。

WCF中的绑定模型&#xff1a;
[WCF中的Binding模型]之一: Binding模型简介
[WCF中的Binding模型]之二: 信道与信道栈&#xff08;Channel and Channel Stack&#xff09;
[WCF中的Binding模型]之三&#xff1a;信道监听器&#xff08;Channel Listener&#xff09;
[WCF中的Binding模型]之四&#xff1a;信道工厂&#xff08;Channel Factory&#xff09;
[WCF中的Binding模型]之五&#xff1a;绑定元素&#xff08;Binding Element&#xff09;
[WCF中的Binding模型]之六&#xff1a;从绑定元素认识系统预定义绑定



推荐阅读
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • Spring框架中枚举参数的正确使用方法与技巧
    本文详细阐述了在Spring Boot框架中正确使用枚举参数的方法与技巧,旨在帮助开发者更高效地掌握和应用枚举类型的数据传递,适合对Spring Boot感兴趣的读者深入学习。 ... [详细]
  • 深入解析CAS机制:全面替代传统锁的底层原理与应用
    本文深入探讨了CAS(Compare-and-Swap)机制,分析了其作为传统锁的替代方案在并发控制中的优势与原理。CAS通过原子操作确保数据的一致性,避免了传统锁带来的性能瓶颈和死锁问题。文章详细解析了CAS的工作机制,并结合实际应用场景,展示了其在高并发环境下的高效性和可靠性。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • ARM汇编基础基于Keil创建STM32汇编程序的编写
    文章目录一、新建项目(1)工具介绍(2)创建项目:二、配置环境(1)配置芯片&#x ... [详细]
  • 开发技巧:在Interface Builder中实现UIButton文本居中对齐的方法与步骤
    开发技巧:在Interface Builder中实现UIButton文本居中对齐的方法与步骤 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • Android 构建基础流程详解
    Android 构建基础流程详解 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • Unity3D 中 AsyncOperation 实现异步场景加载及进度显示优化技巧
    在Unity3D中,通过使用`AsyncOperation`可以实现高效的异步场景加载,并结合进度条显示来提升用户体验。本文详细介绍了如何利用`AsyncOperation`进行异步加载,并提供了优化技巧,包括进度条的动态更新和加载过程中的性能优化方法。此外,还探讨了如何处理加载过程中可能出现的异常情况,确保加载过程的稳定性和可靠性。 ... [详细]
  • POJ 2482 星空中的星星:利用线段树与扫描线算法解决
    在《POJ 2482 星空中的星星》问题中,通过运用线段树和扫描线算法,可以高效地解决星星在窗口内的计数问题。该方法不仅能够快速处理大规模数据,还能确保时间复杂度的最优性,适用于各种复杂的星空模拟场景。 ... [详细]
  • 基于Dubbo与Zipkin的微服务调用链路监控解决方案
    本文提出了一种基于Dubbo与Zipkin的微服务调用链路监控解决方案。通过抽象配置层,支持HTTP和Kafka两种数据上报方式,实现了灵活且高效的调用链路追踪。该方案不仅提升了系统的可维护性和扩展性,还为故障排查提供了强大的支持。 ... [详细]
author-avatar
益林代表_610
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有