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

本节目录:

发送者:通道工厂

IChannelFactory接口

IChannelFactory<TChannel>接口

The ChannelFactoryBase Type ChannelFactoryBase类型

ChannelFactoryBase<TChannel>类型

创建自定义通道工厂

本章小结      

发送者:通道工厂

发送者使用通道工厂来创建通道。它们和通道侦听器的许多特性相似,但是不同的是它们驻留在发送者内部,而且不需要从连接上侦听消息。它们会通过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个参数。它们是EndpointAddressUri类型。在运行时,这些参数会序列化到消息里,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>类型。


 

老徐的博客
【作      者】:Frank Xu Lei
【地      址】:http://www.cnblogs.com/frank_xl/
【中文论坛】:微软WCF中文技术论坛
【英文论坛】:微软WCF英文技术论坛

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值