《WCF技术内幕》翻译39:第2部分_第7章_通道管理器:通道工厂和本章小结

简介:
本节目录:
本章小结        
发送者:通道工厂
发送者使用通道工厂来创建通道。它们和通道侦听器的许多特性相似,但是不同的是它们驻留在发送者内部,而且不需要从连接上侦听消息。它们会通过CreateChannel方法创建符合要求的连接通道而不是消极等待消息到来。和通道侦听器一样,通道工厂也是根据它们创建的通道功能来分类的。
实际上,这意味着每个传输通道都会有一个与之关联的通道工厂,比如支持WS-*协议的通道。和通道侦听器一样,用户代码无法直接实例化通道工厂,需要借助于Binding(你会在第8章里看到详细的介绍)。通道工厂类型都继承自ChannelManagerBase。而类型层次的其它部分则不相同。本节里,我们会先研究一下通道工厂里不同的类型,然后会创建一个自定义通道工厂来继续学习我们的DelegatorChannel例子。
IChannelFactory 接口
所有的通道工厂都继承了IChannelFactory接口。这个接口实现了ICommunicationObject接口,因此可以强制它的继承者实现通道状态机。当然还有就是暴露与通道和通道侦听器里类似的一个查询机制。代码如下所示:
public interface IChannelFactory : ICommunicationObject {
      T GetProperty<T>() where T: class;
}
IChannelFactory<TChannel> 接口
所有的通道工厂也都实现了IChannelFactory<TChannel>接口。这个接口继承自IChannelFactory,所以它比IChannelFactory的用处更广。IChannelFactory<TChannel>定义了2个成员,如下所示:
public interface IChannelFactory<TChannel> : IChannelFactory {
      TChannel CreateChannel(EndpointAddress to);
      TChannel CreateChannel(EndpointAddress to, Uri via);
}
CreateChannel 方法包含2个参数。它们是EndpointAddress Uri类型。在运行时,这些参数会序列化到消息里,via参数就是通道要尝试连接的地址,to是发送消息的地址。中间可能经过消息的中转(第2章里曾经讲到)。
ChannelFactoryBase
类型
通道工厂简介继承了抽象类型ChannelFactoryBase。概念上,它的作用与通道侦听器里使用的ChannelListenerBase类型一样。换句话说,ChannelListenerBase类型也提供了一种自定义打开、关闭、发送和接受消息超时属性的方式。它的对象模型如下所示:
public abstract class ChannelFactoryBase : ChannelManagerBase,
                                           IChannelFactory {
 protected ChannelFactoryBase();
 protected ChannelFactoryBase(IDefaultCommunicationTimeouts timeouts);
 // IChannelFactory implementation
 public virtual T GetProperty<T>() where T: class;
 // CommunicationObject implementation
 protected override  void OnAbort();
 protected override IAsyncResult OnBeginClose(TimeSpan timeout,
                                               AsyncCallback callback,
                                               Object state);
 protected override  void OnClose(TimeSpan timeout);
 protected override  void OnEndClose(IAsyncResult result);
 protected override TimeSpan DefaultCloseTimeout { get; }
 protected override TimeSpan DefaultOpenTimeout { get; }
 // ChannelManagerBase implementation
 protected override TimeSpan DefaultReceiveTimeout { get; }
 protected override TimeSpan DefaultSendTimeout { get; }
}
ChannelFactoryBase<TChannel> 类型
ChannelFactoryBase<TChannel> 类型继承了ChannelFactoryBase类型,而且实现了IChannelFactory<TChannel>接口。它也是通道工厂类型的基类。更进一步说,这个类型维护和控制通道的创建状态。(想一下本章前面“通道管理器的概念”一节。)ChannelFactoryBase<TChannel>的对象模型如下:
public abstract class ChannelFactoryBase<TChannel> : ChannelFactoryBase,
    IChannelFactory<TChannel> {
 // calls the other constructor, passing null as argument
 protected ChannelFactoryBase();
 // creates an object that manages the channels
 protected ChannelFactoryBase(IDefaultCommunicationTimeouts timeouts);
 // IChannelFactory<TChannel> implementation
 public TChannel CreateChannel(EndpointAddress address);
 public TChannel CreateChannel(EndpointAddress address,  Uri via);
 // Extensibility point for IChannelFactory<TChannel> implementation
 protected abstract TChannel OnCreateChannel(EndpointAddress address,  Uri via);
 // CommunicationObject implementation: changes state
 // of the channels it has created
 protected override  void OnAbort();
 protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback,
object  state);
 protected override  void OnClose(TimeSpan timeout);
 protected override  void OnEndClose(IAsyncResult result);
 // helper method that checks the State to see if the
 // channel factory can create channels (CommunicationState.Opened)
 protected  void ValidateCreateChannel();
}
ChannelFactoryBase<TChannel> 的构造函数实例化了一个对象,这个对象可以保存工厂里创建的通道对象的引用。当ChannelFactoryBase<TChannel>对象关闭或者终止的时候,这个对象可以确保引用的通道状态机与ChannelFactoryBase<TChannel>对象状态一致。这些代码确保状态改变发生在ChannelFactoryBase<TChannel>  CommunicationObject的实现里。
ChannelFactoryBase<TChannel> 另外一个有趣的地方就是ValidateCreateChannel方法。这个方法仅仅是为了确保对象的状态是CommunicationState.Opened。如果状态不是,这个方法就会抛出一个InvalidOperationException异常。两个CreateChannel方法都会调用这个方法来确保通道工厂处于正确的状态。
创建自定义通道工厂
既然已经学习了通道工厂里重要的相关类型,现在我们来创建一个自定义通道工厂,继续完成我们的DelegatorChannel例子。和前面的DelegatorChannelListener<TShape>例子类似,我们的通道工厂必须可以创建任何形状的通道。因此,我们的通道工厂必须使用泛型,如下所示:
internal sealed class DelegatorChannelFactory<TShape> :
    ChannelFactoryBase<TShape> {
 // reference the next channel factory in the stack
 IChannelFactory<TShape> _innerFactory;
 // the String to print to the console
 String _consolePrefix = "FACTORY: DelegatorChannelFactory";
 // ctor that builds the next channel factory in the stack,
 // then assigns the _innerFactory member variable
 internal DelegatorChannelFactory(BindingContext context) {
    PrintHelper.Print(_consolePrefix, "ctor");
    this._innerFactory = context.BuildInnerChannelFactory<TShape>();
 }
 // instantiates and returns a DelegatorChannel that
 // references another channel
 private TShape WrapChannel(TShape innerChannel) {
    if(innerChannel == null) {
      throw new ArgumentNullException("innerChannel cannot be null",
        "innerChannel");
    }
    if(typeof(TShape) == typeof(IOutputChannel)) {
      return (TShape)(Object) new DelegatorOutputChannel<IOutputChannel>
        (this, (IOutputChannel)innerChannel, "SEND");
    }
    if(typeof(TShape) == typeof(IRequestChannel)) {
      return (TShape)(Object) new DelegatorRequestChannel
        (this, (IRequestChannel)innerChannel, "SEND");
    }
    if(typeof(TShape) == typeof(IDuplexChannel)) {
      return (TShape)(Object) new DelegatorDuplexChannel
        (this, (IDuplexChannel)innerChannel, "SEND");
    }
    if(typeof(TShape) == typeof(IOutputSessionChannel)) {
      return (TShape)(Object) new DelegatorOutputSessionChannel
        (this, (IOutputSessionChannel)innerChannel, "SEND");
    }
    if(typeof(TShape) == typeof(IRequestSessionChannel)) {
      return (TShape)(Object) new DelegatorRequestSessionChannel
        (this, (IRequestSessionChannel)innerChannel, "SEND");
    }
    if(typeof(TShape) == typeof(IDuplexSessionChannel)) {
      return (TShape)(Object) new DelegatorDuplexSessionChannel
        (this, (IDuplexSessionChannel)innerChannel, "SEND");
    }
    // cannot wrap this channel
    throw new ArgumentException(String.Format("invalid channel shape
      passed:{0}", innerChannel.GetType()));
 }
 // uses the _innerFactory member variable to build a channel
 // then wraps it and returns the wrapped channel
 protected override TShape OnCreateChannel(EndpointAddress address,
    Uri via) {
    // create and return the channel
    PrintHelper.Print(_consolePrefix, "OnCreateChannel");
    TShape innerChannel = this._innerFactory.CreateChannel(address, via);
    return WrapChannel(innerChannel);
 }
 protected override IAsyncResult OnBeginOpen(TimeSpan timeout,
                                              AsyncCallback callback,
                                              Object state) {
    PrintHelper.Print(_consolePrefix, "OnBeginChannel");
    return this._innerFactory.BeginOpen(timeout, callback, state);
 }
 protected override void OnAbort() {
    base.OnAbort();
    PrintHelper.Print(_consolePrefix, "OnAbort");
 }
 protected override void OnClose(TimeSpan timeout) {
    base.OnClose(timeout);
    PrintHelper.Print(_consolePrefix, "OnClose");
 }
 protected override void OnEndOpen(IAsyncResult result) {
    PrintHelper.Print(_consolePrefix, "OnEndOpen");
    this._innerFactory.EndOpen(result);
 }
 protected override void OnOpen(TimeSpan timeout) {
    PrintHelper.Print(_consolePrefix, "OnOpen");
    this._innerFactory.Open(timeout);
 }
 public override T GetProperty<T>() {
    PrintHelper.Print(_consolePrefix, "GetProperty<" + typeof(T).Name +
      ">");
    return this._innerFactory.GetProperty<T>();
 }
}
定义上来看,DelegatorChannelFactory<TShape>与DelegatorChannelListener<TShape>很相似,它定义了一个私有的WrapChannel方法,可以把一个通道包装为特定的形状,然后返回。当然也定义了另外几个方法,这些方法可以把状态转换传递给成员变量innerFactory的。

本章小结

WCF类型通过通道工厂和通道侦听器来创建通道。通道侦听器负责侦听可用的连接。通道工厂和通道侦听器的架构模型与伯克利的Sockets API十分相似,和通道一样,通道工厂和通道侦听器也是在运行时组装到堆栈的,并且堆栈里的每个通道侦听器或通道工厂都负责创建一个通道。另外就是传输通道工厂或者通道侦听器必须位于堆栈的底部。此外,用户代码不能直接实例化通道侦听器和通道工厂。这些工作有BindingElement完成。 Binding 和BindingElement对象会在下一章里讲到,而且作为总结部分,你会看到我们定义的 DelegatorChannel  通道、以及DelegatorChannelListener<TShape> 和DelegatorChannelFactory<TShape>类型。



 本文转自 frankxulei 51CTO博客,原文链接: http://blog.51cto.com/frankxulei/318549 ,如需转载请自行联系原作者



相关文章
|
9月前
|
前端开发
WCF更新服务引用报错的原因之一
WCF更新服务引用报错的原因之一
|
8月前
|
C# 数据安全/隐私保护
c#如何创建WCF服务到发布(SqlServer版已经验证)
c#如何创建WCF服务到发布(SqlServer版已经验证)
38 0
|
8月前
|
安全 数据库连接 数据库
WCF服务创建到发布(SqlServer版)
在本示例开始之前,让我们先来了解一下什么是wcf? wcf有哪些特点? wcf是一个面向服务编程的综合分层架构。该架构的项层为服务模型层。 使用户用最少的时间和精力建立自己的软件产品和外界通信的模型。它使得开发者能够建立一个跨平台的安全、可信赖、事务性的解决方案。且能与已有系统兼容写作。 简单概括就是:一组数据通信的应用程序开发接口。
57 0
Visual Studio 2022 创建 WCF服务 找不到
Visual Studio 2022 创建 WCF服务 找不到
|
C++
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题
102 0
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题