客户端体系结构

应用程序使用 Windows Communication Foundation (WCF) 客户端对象来调用服务操作。 本主题讨论 WCF 客户端对象、WCF 客户端通道以及它们与基础通道体系结构的关系。 有关 WCF 客户端对象的基本概述,请参阅 WCF 客户端概述。 有关通道层详细信息,请参阅扩展通道层

概述

服务模型运行时创建 WCF 客户端,这些客户端由以下各项构成:

  • 自动生成的服务协定客户端实现,该实现可以将应用程序代码中的调用转换为传出消息,将响应消息转换为输出参数并返回应用程序可以检索的值。

  • 控制接口 (System.ServiceModel.IClientChannel) 的实现,它可将各个接口组合在一起,并提供对控制功能(特别是用于关闭客户端会话和释放通道的能力)的访问。

  • 基于由使用的绑定指定的配置设置而生成的客户端通道。

应用程序可以根据需要通过 System.ServiceModel.ChannelFactory 或通过创建由 ServiceModel 元数据实用工具 (Svcutil.exe) 生成的 ClientBase<TChannel> 派生类的实例来创建这样的客户端。 这些预先生成的客户端类可以封装并委托给由 ChannelFactory 动态构造的客户端通道实现。 因此,客户端通道和生成这些客户端通道的客户端工厂是此处讨论的焦点。

客户端对象和客户端通道

WCF 客户端的基接口是 System.ServiceModel.IClientChannel 接口,该接口公开核心客户端功能以及 System.ServiceModel.ICommunicationObject 的基本通信对象功能、System.ServiceModel.IContextChannel 的上下文功能和 System.ServiceModel.IExtensibleObject<T> 的可扩展行为。

IClientChannel 接口并不定义服务协定本身。 这些协定通过服务协定接口进行声明(通常使用 ServiceModel 元数据实用工具 (Svcutil.exe) 这样的工具从服务元数据生成)。 WCF 客户端类型同时扩展 IClientChannel 和目标服务协定接口,以使应用程序能够直接调用操作,同时还可以访问客户端运行时功能。 创建一个 WCF 客户端可以向 WCFSystem.ServiceModel.ChannelFactory 对象提供必要信息,以便创建可以连接到配置的服务终结点并与此终结点交互的运行时。

如前所述,这两个 WCF 客户端类型必须进行配置才能使用。 最简单的 WCF 客户端类型是从 ClientBase<TChannel> 中派生的对象(如果服务协定是双工协定,则为从 DuplexClientBase<TChannel> 中派生的对象)。 通过使用以编程方式进行配置的构造函数,或者通过使用配置文件,然后直接调用该配置文件以调用服务操作,可以创建这些类型。 有关 ClientBase<TChannel> 端对象的基本概述,请参阅 WCF 客户端概述

第二个类型是在运行时从对 CreateChannel 方法的调用中生成的。 涉及严格控制通信详细信息的应用程序通常使用这种称为“客户端通道对象”的客户端类型,因为与基础客户端运行时和通道系统相比,它可以启用更直接的交互。

通道工厂

负责创建可支持客户端调用的基础运行时的类为 System.ServiceModel.ChannelFactory<TChannel> 类。 WCF 客户端对象和 WCF 客户端通道对象都使用 ChannelFactory<TChannel> 对象来创建实例;ClientBase<TChannel> 派生的客户端对象封装通道工厂的处理,但在有些情况下,完全可以直接使用通道工厂。 对此,常见的情况是从现有工厂重复创建新的客户端通道。 如果要使用客户端对象,可以通过调用 ClientBase<TChannel>.ChannelFactory 属性从 WCF 客户端对象中获取基础通道工厂。

应该记住的是,在调用 ChannelFactory<TChannel>.CreateChannel 之前,通道工厂会为所提供的配置创建客户端通道的新实例。 一旦调用 CreateChannel(或 ClientBase<TChannel>.OpenClientBase<TChannel>.CreateChannel 或对 WCF 客户端对象执行的任何操作)后,不能修改通道工厂和期待获取到不同服务实例的通道,即使只是更改目标终结点地址也是如此。 如果您想用不同配置创建客户端对象或客户端通道,则必须首先创建新的通道工厂。

有关使用 WCF 客户端对象和 WCF 客户端通道的各种问题的详细信息,请参阅使用 WCF 客户端访问服务

以下两节说明 WCF 客户端通道对象的创建和使用。

创建新的 WCF 客户端通道对象

为了说明客户端通道的用法,假设已生成以下服务协定。

[System.ServiceModel.ServiceContractAttribute(
  Namespace = "http://microsoft.wcf.documentation"
)]
public interface ISampleService
{
    [System.ServiceModel.OperationContractAttribute(
      Action = "http://microsoft.wcf.documentation/ISampleService/SampleMethod",
      ReplyAction = "http://microsoft.wcf.documentation/ISampleService/SampleMethodResponse"
    )]
    [System.ServiceModel.FaultContractAttribute(
      typeof(microsoft.wcf.documentation.SampleFault),
      Action = "http://microsoft.wcf.documentation/ISampleService/SampleMethodSampleFaultFault"
    )]
    string SampleMethod(string msg);
}

若要连接到 ISampleService 服务,请直接与通道工厂 (ChannelFactory<TChannel>) 一起使用生成的协定接口。 一旦为特定协定创建并配置通道工厂后,即可以调用 CreateChannel 方法以返回可用于与 ISampleService 服务通信的客户端通道对象。

ChannelFactory<TChannel> 类与服务协定接口一起使用时,您必须强制转换到 IClientChannel 接口以显式打开、关闭或中止通道。 为便于操作,Svcutil.exe 工具还生成一个帮助器接口,该接口可同时实现服务协定接口和 IClientChannel ,以使您无需进行强制转换就能够与客户端通道基础结构进行交互。 下面的代码演示实现上述服务协定的帮助器客户端通道的定义。

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface ISampleServiceChannel : ISampleService, System.ServiceModel.IClientChannel
{
}

创建新的 WCF 客户端通道对象

若要使用客户端通道连接到 ISampleService 服务,请直接与通道工厂一起使用生成的协定接口(或帮助器版本),将协定接口的类型作为类型参数进行传递。 一旦为特定协定创建并配置通道工厂后,即可以调用 ChannelFactory<TChannel>.CreateChannel 方法以返回可用于与 ISampleService 服务通信的客户端通道对象。

客户端通道对象在创建后可实现 IClientChannel 和协定接口。 因此,可以直接使用这些对象来调用操作,与支持该协定的服务进行交互。

使用客户端对象和客户端通道对象之间的区别仅仅在于其易于使用性和开发人员的喜好。 许多习惯于使用类和对象的开发人员喜欢使用 WCF 客户端对象,而不喜欢使用 WCF 客户端通道。

有关示例,请参阅如何:使用 ChannelFactory