WCF之Channel(二)

接下来说ChannelListener和ChannelFactory。

ChannelListener是Service端的技术,用来侦听消息,创建信道栈,并为应用程序提供指向栈顶的引用。

我们不会直接使用ChannelListener,但是我们经常会使用到ServiceHost,殊途同归,其实也是用它来侦听消息。

static void Main(string[] args)
{
    BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None);

    Uri address = new Uri("http://localhost/request");

    Console.WriteLine("Starting Service...");

    IChannelListener<IReplyChannel> listener = binding.BuildChannelListener<IReplyChannel>(address, new BindingParameterCollection());
    listener.Open();

    IReplyChannel channel = listener.AcceptChannel();
    channel.Open();

    Console.WriteLine("Service Started~");

    Console.WriteLine("Waiting for request...");

    RequestContext request = channel.ReceiveRequest();
    Message message = request.RequestMessage;
    string data = message.GetBody<string>();

    Message replyMessage = Message.CreateMessage(message.Version, "http://localhost/reply", data);

    request.Reply(replyMessage);
    Console.WriteLine("Service stopped!");

    message.Close();
    request.Close();
    channel.Close();
    listener.Close();

    Console.ReadLine();
}

 

ChannelFactory是Client端的技术,用来发送消息和定义它所创建的channel的所有者。

我们不会直接使用ChannelFactory,但是我们经常会见到ClientBase<T>,就是在Add Service Reference后自动生成的代码。

static void Main(string[] args)
{
    BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None);

    IChannelFactory<IRequestChannel> factory = binding.BuildChannelFactory<IRequestChannel>(new BindingParameterCollection());

    factory.Open();

    IRequestChannel channel = factory.CreateChannel(new EndpointAddress("http://localhost/request"));
    channel.Open();

    Message requestMessage = Message.CreateMessage(MessageVersion.Soap11, "http://localhost/reply", "This is the body data");

    Console.WriteLine("Sending message...");

    Message replyMessage = channel.Request(requestMessage);

    string data = replyMessage.GetBody<string>();
    Console.WriteLine("Reply received~");

    requestMessage.Close();
    replyMessage.Close();
    channel.Close();
    factory.Close();

    Console.ReadLine();
}

 

上面两段代码共同组成一个request-reply的Demo,代码下载:RequestReply.zip

 

ChannelListener和ChannelFactory的区别是,前者会关闭全部相关的channel,而后者不会。

 

ChannelFactory<T>区别于ChannelFactory,前者用于创建多个Client。

 

最后提到ICommunicationObject,所有的Channel、ChannelListener和ChannelFactory都实现了这个接口,例如:

IOutputChannel : IChannel, ICommunicationObject

这个接口是为了实现状态机。

image

注意到这个接口的State属性,它是一个enum,对应了状态机的所有state:

public enum CommunicationState
{
    Created = 0,
    Opening = 1,
    Opened = 2,
    Closing = 3,
    Closed = 4,
    Faulted = 5,
}

image

 

ClientBase<T>就是实现了ICommunicationObject接口。

 

此外,WCF还提供了一个抽象类CommunicationObject,也实现了ICommunicationObject接口,并实现了状态机,所以我们可以使用ICommunicationObject接口暴露的那些event。我们只要从这个抽象类中派生,就可以自定义自己的方法和事件。

WCF本质论P109页的这个例子,是把一个Client转换为ICommunicationObject接口,从而在接口暴露的事件上附加自定义的方法:

image

 

至此,Channel全都说完,不过,可惜啊可惜,这些内容只能用来加深我们对WCF的理解,而很少在实际中运用。WCF开发Team需要想想为什么了。

posted @ 2009-11-07 18:37  包建强  Views(1467)  Comments(0Edit  收藏  举报