西北狼

-- 学而时习之,不亦乐乎!
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Windows Communication Foundation 编程的基础知识

Posted on 2010-04-20 20:26  西北老狼  阅读(338)  评论(0编辑  收藏  举报

Windows® Communication Foundation (WCF)(以前的代号为“Indigo”)将为使用 Microsoft® .NET Framework 的开发人员从根本上改变分布式编程的接口。WCF 将现有的整套 .NET 分布式技术整合为一个编程模型,通过稳定的结构、极大改进的功能性和互操作性以及您希望拥有的所有可扩展性,全面改善了您的体验。本文将向您介绍 WCF 编程以及如何快速入门。

正如其名称表明的那样,WCF 为 .NET Framework 提供了一个基础,使其能够编写代码,以在组件、应用程序和系统之间进行通信。WCF 的设计遵循的是面向服务的原则。服务是指可以通过消息与之进行交互的一段代码。服务是被动的。它们等待传入消息后才开始工作。客户端是发起者。客户端将消息发送给服务来请求工作。


图 1:服务和端点


服务提供一个或多个端点,可将消息发送到这些端点。每个端点由一个地址、一个绑定和一个合同组成(请参见图 1)。地址指定发送消息的目标位置;绑定描述如何发送消息;合同描述消息所包含的内容。客户端需要先获知此信息才能访问服务。

服务可以将端点描述打包以实现与客户端的共享,一般通过使用 Web 服务描述语言 (WSDL) 来实现。随后,客户端可以使用所提供的服务描述在其环境内(能够发送和接收正确的消息)生成代码(请参见图 2)。


图 2:共享端点描述


Windows Communication Foundation 提供了一个位于 System.ServiceModel 命名空间中的新的类库,使这些面向服务的概念成为现实。这就是通常所说的 WCF 编程模型。

WCF 编程模型


通过 WCF,您可以编写提供端点的服务,也可以编写与端点进行交互的客户端。因此,端点是 WCF 编程模型和基础结构的核心。具有 .NET 类和接口的 WCF 模型端点如图3 所示。无论您编写的是 WCF 客户端还是服务,该映射都是正确的。

在建立 WCF 服务时,通常首先定义用作服务合同的 .NET 接口定义。然后在 .NET 类(称为服务类型)中实施服务合同并配置其行为。接下来,定义服务要提供的端点,并为每个端点指定位置、绑定及合同。最后,使用 WCF 托管基础结构在应用程序中托管服务类型。服务类型被托管后,客户端就可以检索其端点描述并开始与其集成。

建立 WCF 客户端时,首先需要获得要访问的目标端点的描述。该端点描述可用于动态地创建一个类型代理。WCF 提供了一种名为 SvcUtil.exe 的工具来自动执行该进程。然后,您可以针对类型代理编写代码,通过向目标端点发送相应的消息来访问服务。

服务合同和调度行为


使用传统的 C# 接口定义在 .NET 中建立服务合同。可以将任意 .NET 接口作为起始点,如以下所示:

namespace ServiceLibrary
{
public interface IEchoService
    {
string Echo(string msg);
    }
}

要使其成为 WCF 服务合同,必须使用 [ServiceContract] 为接口本身添加批注,使用 [OperationContract] 为要提供的每个操作添加批注:

using System.ServiceModel;

namespace ServiceLibrary
{
[ServiceContract(Namespace="http://example.org/echo/")]
public interface IEchoService
    {
[OperationContract]
string Echo(string msg);
    }
}

这些属性影响 .NET 领域和 SOAP 领域之间的映射。WCF 使用服务合同中的信息来执行调度和序列化。调度是为传入的 SOAP 消息确定调用方法的过程。序列化是 SOAP 消息中的数据和方法调用中使用的相应 .NET 对象之间映射的过程。该映射由操作的数据合同进行控制。

WCF 根据消息动作进行调度。服务合同中的每个方法都将根据服务命名空间和方法名称自动被指定一个动作值。例如,刚才所示的 Echo 方法的默认动作为 http://example.org/echo/Echo。可以使用 [OperationContract] 为每个方法自定义动作值。如果具体匹配不存在,可使用值 * 来代表任意动作。

在下例中,WCF 会将带有 urn:echo:string 动作的消息调度到 Echo 方法,并将带有任何其他动作的消息调度到 EchoMessage 方法:

[ServiceContract(Namespace="http://example.org/echo/")]
public interface IEchoService
{
[OperationContract(Action="urn:echo:string")]
string Echo(string msg);

[OperationContract(Action="*")]
Message EchoMessage(Message msg);
}

数据合同


根据动作确定目标方法后,WCF 将依靠该方法的数据合同来执行序列化。数据合同由方法签名中使用的类型进行定义。在上例中,EchoMessage 是通用的,可用于处理多种传入的 SOAP 消息。因此,我已经使用 Message 来建立输入和输出。Message 是一种特殊类型,用于表示流经 WCF 的所有消息。使用 Message 时,WCF 不执行基于类型的序列化。而是使您可以直接访问存在于 SOAP 消息中的内容。

不使用 Message 时,WCF 将执行序列化以在存在于 SOAP 消息中的数据和需要调用方法的相应 .NET 对象之间建立映射。例如,对于 Echo,WCF 将 SOAP 有效负载映射到一个 .NET 字符串。WCF 为所有 .NET 原始类型(字符串、整数、双精度等)提供隐含映射。

WCF 序列化 .NET 类的方式取决于正在使用的序列化引擎。默认的序列化引擎称为 DataContract,它是目前在 ASMX 中使用的默认序列化引擎 XmlSerializer 的简化版本。DataContract 定义批注类定义的属性,以便影响序列化进程。以下为使用 DataContract 的示例:

[DataContract(Namespace="http://example.org/person")]
public class Person
{
[DataMember(Name="first", Order=0)]
public string First;
[DataMember(Name="last", Order=1)]
public string Last;
[DataMember(IsRequired=false, Order=2)]
private string id;
    ...
}

使用 DataContract,只能序列化标有 DataMember 的字段。还可以序列化私有字段。这与 XmlSerializer 的作用方式大不相同。现在,可以在操作合同中使用 Person:

[ServiceContract(Namespace="http://example.org/echo/")]
public interface IEchoService
{
... //先前的方法已省略

[OperationContract]
Person EchoPerson(Person p);
}

调用 EchoPerson 后,WCF 将根据在 Person 类上指定的 DataContract 属性来序列化 Person 实例。DataContract 将生成一种非常简单的 XML 结构,即元素序列。可以控制每个元素的名称、顺序以及是否需要特殊元素,但也只能控制这些。

如果需要执行更复杂的操作,WCF 允许您后退,以使用 XmlSerializer。您通过使用 [XmlSerializerFormat] 批注接口来表明要使用 XmlSerializer:

[ServiceContract]
[XmlSerializerFormat]
public interface IEchoService { ... }

这会要求 WCF 根据 XmlSerializer 默认值和不同的 System.Xml.Serialization 自定义属性来对合同中的所有类型都使用 XmlSerializer。这使得将现有 ASMX 服务移动到 WCF 更加轻松。

WCF 还支持对标有 [Serializable] 的类型进行序列化,从而可以不更改 .NET 远程类型就能与 WCF 一起使用。WCF 为 [Serializable] 类型提供隐含映射,在其中将自动序列化所有公共/私有字段。

消息和服务合同


到现在为止的所有示例均依靠 WCF 将方法签名自动映射到 SOAP 消息。参数列表和返回类型将始终分别映射到请求和响应的 SOAP 主体。如果需要支持标题,可以编写另一个类来为个别操作建立整个 SOAP 封装的结构,同时指定哪些字段映射到标题和主体。使用 [MessageContract] 属性定义该映射:

[MessageContract]
public class EchoPersonMessage
{
[MessageBody]
public Person Person;
[MessageHeader]
public Authorization Authorization;
}

在本例中,Person 字段被映射到 SOAP 主体,而 Authorization 字段被映射到 SOAP 标题。现在,可以在操作合同中使用 EchoPersonMessage:

[ServiceContract]
public interface IEchoService
{
... //先前的方法已省略

[OperationContract]
void EchoPerson(EchoPersonMessage msg);
}

Using MessageContract 是一项更先进的技术,仅在需要对 SOAP 合同进行直接控制时才有必要使用该技术。

实施服务合同


现在,只需通过在类中实现 .NET 接口即可实施服务合同:

using System.ServiceModel;
namespace ServiceLibrary
{
public class EchoService :IEchoService
    {
public string Echo(string msg)
        {
return msg;
        }
... //其余的方法已省略
    }
}

执行此操作,将确保 EchoService 支持由 IEchoService 定义的服务合同。使用接口定义服务合同时,不需要类定义上的任何与合同相关的属性。然而,您可能希望使用 [ServiceBehavior] 来影响其本地行为:

using System.ServiceModel;

namespace ServiceLibrary
{
... //接口定义已省略

[ServiceBehavior(
InstanceContextMode=InstanceContextMode.Single,
ConcurrencyMode=ConcurrencyMode.Multiple)]
public class EchoService :IEchoService
    {
       ...

该特殊示例要求 WCF 管理服务类型的单个实例以及允许对该实例的多线程访问。还存在一个用于控制操作级别行为的 [OperationBehavior] 属性。

行为会影响主机内的进程,但绝不会影响服务合同。行为是其中一个主要的 WCF 可扩展性要点。实现 IServiceBehavior 的任何类都可以通过使用自定义属性或配置元素而被应用到服务中。

托管服务和定义端点


要使用 EchoService,需要在基于 .NET 的应用程序中对其进行托管。ServiceHost 类使您可以对 WCF 托管基础结构进行直接控制。您可以根据特定的服务类型实例化 ServiceHost。以下代码显示了如何在控制台应用程序中执行该操作:

using System;
using System.ServiceModel;
using ServiceLibrary;

class Program
{
static void Main(string[] args)
    {
using (ServiceHost host = new ServiceHost(
typeof(EchoService), new Uri("http://localhost:8080/echo")))
        {
            ...

除指定服务类型之外,还需要为计划使用的各个传输指定基址。在本例中,我已指定了一个基址 http://localhost:8080/echo。该地址将用作任何相对 HTTP 地址(我可能在添加端点时指定)的基址。HTTP 基址还用作检索服务描述的默认地址。

然后,添加服务端点。此外,服务可能包含一个或多个端点,每个端点都由一个地址、一个绑定和一个合同组成。通过调用 AddServiceEndpoint 为 ServiceHost 提供该信息。这是您指定先前所定义服务合同 (IEchoService) 的位置。对于绑定,通常从 WCF 附带的许多预定义的绑定和给定绑定传输的相应地址中进行选择。下面是一个示例:

host.AddServiceEndpoint(typeof(IEchoService),
new BasicHttpBinding(), "svc");
host.AddServiceEndpoint(typeof(IEchoService),
new NetTcpBinding(), "net.tcp://localhost:8081/echo/svc");

在此特殊示例中,我已将 IEchoService 指定为两个端点的合同,但每个端点都使用不同的绑定和地址。第一个端点使用 BasicHttpBinding 和 svc 相对 HTTP 地址(将 http://localhost:8080/echo/svc 作为其绝对地址)。第二个端点使用 NetTcpBinding 和地址 net.tcp://localhost:8081/echo/svc。因此,该服务允许使用者使用不同的 WS-* 协议(由每个绑定定义)通过 HTTP 或 TCP 与其通信。

选择和自定义绑定


WCF 基础结构严重依赖端点定义来控制处理消息的方式。实际上,WCF 使用端点定义来动态地建立主机与客户端之间的相应消息处理运行时。绑定对该过程具有最显著的影响。

绑定控制消息通信的三个方面:WS-* 协议的套件,包括 WS-Security、WS-ReliableMessaging 等;消息编码方式,例如 XML 1.0、消息传输优化机制 (MTOM) 和二进制;传输协议,包括 HTTP、TCP 和 Microsoft Message Queuing (MSMQ)。一个给定的绑定指定一种消息编码方式和一个传输,但可以指定多个 WS-* 协议。因此,存在相当多的排列可以使用。为了简化需要,WCF 提供一套预定义的绑定,适用于最常用的情况。图4 列出了部分绑定并描述了它们所表示的内容。

那些注重互操作性但不需要 WS-* 功能的开发人员通常会使用 BasicHttpBinding。那些注重互操作性、但同时也需要基于消息的安全、可靠的消息传送和事务的开发人员通常会选择 WSHttpBinding。在两端(客户端和服务)上同时使用 WCF 的开发人员可以从 NetTcpBinding 和 NetNamedPipeBinding 中选择,从而提供显著的优化。那些组建异步系统的开发人员可以选择 NetMsmqBinding。还有少数绑定未列于此,例如用于与现有 MSMQ 应用程序进行集成的 MsmqIntegrationBinding、用于组建对等网络服务的 NetPeerTcpBinding 以及用于联合安全性的 WSFederationBinding。服务可以支持这些绑定的任意组合。

选择并实例化一个绑定后,可以通过绑定类上提供的属性来自定义它的某些特征。下例显示了如何在 BasicHttpBinding 上启用基于传输的安全性:

BasicHttpBinding b = new BasicHttpBinding();
b.Security.Mode = BasicHttpSecurityMode.Transport;
b.Security.Transport.ClientCredentialType = 
HttpClientCredentialType.Basic;
host.AddServiceEndpoint(typeof(IEchoService), b, "svc");

如果预定义绑定及其自定义仍然不能满足您的要求,还可以通过实现从绑定派生的类来编写自定义绑定。

打开主机


既然已经使用端点信息配置了主机,那么 WCF 就可以建立支持您的配置所需要的运行时。当您在特定的 ServiceHost 上调用 Open 时会发生这种情况:

host.Open();

返回对 Open 的调用后,WCF 运行时已建立并准备在每个端点指定的地址处接收消息。在此过程中,WCF 为每个提供的端点生成了一个端点侦听程序,并生成了支持由绑定指定的 WS-* 协议所需的代码。(端点侦听程序是一段代码,实际上,它使用指定的传输和地址侦听传入的消息)。

您可以通过 ServiceHost 提供的对象模型来检索关于在运行时的服务的信息。这使您可以检索可能希望获知的有关初始化服务的任何信息,例如,服务所提供的端点以及当前活动的端点侦听程序。

图5 显示了一个关于托管 EchoService 的控制台应用程序的完整示例。图 6 显示了输出。请注意,有两个我并未在 ServiceEndpoint 中指定的附加端点侦听程序地址。通过使用 HTTP 基址检索服务描述,WCF 自动提供了这些地址。


图 6:控制台应用程序的输出


如果浏览 http://localhost:8080/echo,您将看到默认的 WCF 帮助页面(请参见图 7),如果浏览 http://localhost:8080/echo?wsdl,您将看到生成的 WSDL 定义。另一个端点侦听程序 (http://localhost:8080/echo/mex) 知道如何表达 WS-MetadataExchange。需要注意的很重要的一点是,该示例未以任何方式使用 IIS。WCF 提供了与 httpsys 的内嵌式集成,这样可以使任意应用程序自动成为一个 HTTP 侦听程序。


图 7:EchoService 帮助页面


配置服务端点


由于端点详细信息可能会随时间的推移而变化,因此将端点信息硬编码到主机应用程序中并不是理想的方法。不难想象如何才能将端点信息存储到配置文件或数据库中,并在初始化 ServiceHost 时读取该信息。由于这是一个常见需求,因此 WCF 通过预定义的 <system.serviceModel> 配置区段自动提供该功能。

以下配置文件定义了已通过调用 AddServiceEndpoint 指定的两个相同的端点:

<configuration>
<system.serviceModel>
<services>
<service type="ServiceLibrary.EchoService">
<endpoint address="svc" binding="basicHttpBinding"
contract="ServiceLibrary.IEchoService"/>
<endpoint address="net.tcp://localhost:8081/echo/svc"
binding="netTcpBinding"
contract="ServiceLibrary.IEchoService"/>
</service>
</services>
</system.serviceModel>
</configuration>

如果将该配置文件添加到图5 所示的主机应用程序并标注对 AddServiceEndpoint 的调用,您将会在输出中看到相同的结果。由于通信详细信息已经从编译代码中完全分解出来,因此这会提高部署的灵活性。您还可以在 <system.serviceModel> 中配置绑定。图8 显示了如何配置 basicHttpBinding 以使用传输安全性(正如我在代码中已经使用的)。

甚至可以使用 <customBinding> 元素从头开始定义新的自定义绑定,这等同于从 Binding 中派生一个新类。当开始配置端点、绑定甚至行为时,在代码中可以执行的任何操作,在配置时也都可以执行。


图 9:使用 GUI 定义端点


尽管用于配置文件的 IntelliSense® 可以在 Visual Studio® 2005 中运行得很好,但是某些开发人员依旧从来不使用 XML。WinFX® SDK 包括一个名为 SvcConfigEditor 的工具,该工具提供了一个可以与多种 <system.serviceModel> 设置一起使用的图形界面。图 9 显示了如何使用该工具配置端点。

使用激活服务


尽管我一直在尝试控制台应用程序,但 ServiceHost 使得在各种应用程序(包括 Windows Forms 应用程序和管理 Windows 服务)中托管 WCF 服务更加便捷。在所有这些应用程序方案中,您负责管理托管 WCF 的过程。这在 WCF 术语中称为自托管。

除自托管之外,WCF 还通过将 IIS 与传统的 Web 托管技术结合使用,使激活服务成为可能。可以通过使用 .svc 文件(与 .asmx 类似)指定要托管的服务类型来完成此操作:

<%@Service class="ServiceLibrary.EchoService" %>

将该文件放到一个虚拟目录中,并将服务类型部署到其 \bin 目录或全局程序集缓存 (GAC) 中。使用该技术时,您在 web.config 中指定服务端点,但由于 .svc 文件位置已经隐含了该地址,因此无需再指定地址。

<configuration>
<system.serviceModel>
<services>
<service type="ServiceLibrary.EchoService">
<endpoint address="" binding="basicHttpBinding"
contract="ServiceLibrary.IEchoService"/>
</service>
      ...

如果现在浏览到 .svc 文件,您会注意到已显示帮助页面,表示已在 ASP.NET 应用程序域中自动创建了 ServiceHost。该操作由一个 HTTP 模块完成,此模块可以过滤传入的 .svc 请求并在需要时自动建立和打开相应的 ServiceHost。

如果安装 Visual Studio 2005 的 WinFX 扩展,您会发现一个名为 Indigo Service(该名称将更改)的新 Web 站点项目模板。根据该模板创建新的 Web 站点时,它将自动向您提供 .svc 文件和相应的实现类(存在于 App_Code 中)。该模板还在 web.config 中附带了一个默认的端点配置。

在 IIS 5.1 版和 6.0 版中,WCF 激活模型被捆绑到 ASP.NET 流水线,因此也就被捆绑到 HTTP。IIS 7.0(计划与 Windows Vista 一起发布)引入了中立传输激活机制,称为 Windows 激活服务 (WAS)。通过 WAS,您可以在任何传输中应用 .svc 之类的激活。

进行客户端编程


进行 WCF 客户端编程包括根据服务端点的地址、绑定和合同向其发送消息。要完成该操作,首先要创建 ServiceEndpoint 来表示目标端点。下例显示了如何根据服务的 HTTP 端点在客户端控制台应用程序中创建 ServiceEndpoint:

using System;
using System.ServiceModel;
using ServiceLibrary;

class Program
{
static void Main(string[] args)
    {
ServiceEndpoint httpEndpoint = new ServiceEndpoint(
ContractDescription.GetContract(typeof(IEchoService)),
new BasicHttpBinding(), new EndpointAddress(
"http://localhost:8080/echo/svc");

该代码假定客户端可以访问该服务所使用的同一 IEchoService 接口定义,并且假定客户端知道要使用的绑定和地址。然后,可以根据 ServiceEndpoint 创建 ChannelFactory:

ChannelFactory<IEchoService> factory =
new ChannelFactory<IEchoService>(httpEndpoint);

ChannelFactory 用于创建类型代理。在本例中,它创建了 IEchoService 类型的代理,您可以使用该代理调用由合同定义的操作:

IEchoService svc = factory.CreateChannel();
Console.WriteLine(svc.Echo("Hello, world"));

如果服务需要一个自定义绑定,您必须在创建 ServiceEndpoint 之前创建该绑定并对其进行自定义。如果您要访问 TCP 端点,只需创建另一个 ServiceEndpoint 来指定 TCP 端点详细信息并将其提供给 ChannelFactory 而不是 HTTP 端点即可。其他所有项目保持不变。

代理使您可以避免使用不同的地址和绑定,并允许您针对服务合同编写应用程序代码。图10 显示了完整的客户端控制台应用程序。

配置客户端端点


将端点信息硬编码到客户端代码也不是很理想的方法。因此,WCF 提供了一个类似的配置机制用于在 <system.serviceModel> 中指定客户端端点。以下应用程序配置文件指定了在该代码中使用的同一客户端端点详细信息:

<configuration>
<system.serviceModel>
<client>
<endpoint name="httpEndpoint" 
address="http://localhost:8080/echo/svc"
binding="basicHttpBinding"
contract="ServiceLibrary.IEchoService"/>
<endpoint name="tcpEndpoint" 
address="net.tcp://localhost:8081/echo/svc"
binding="netTcpBinding"
contract="ServiceLibrary.IEchoService"/>
</client>
</system.serviceModel>
</configuration>

请注意,我已经为每个客户端端点指定了名称。创建 ChannelFactory 时,可以在您的代码中使用这个名称,如以下代码所示:

using (ChannelFactory<IEchoService> httpFactory = 
new ChannelFactory<IEchoService>("httpEndpoint"))
{
svc = httpFactory.CreateChannel();
Console.WriteLine("Invoking HTTP endpoint: {0}",
svc.Echo("Hello, world"));
}

现在,如果要为 TCP 端点创建一个 ChannelFactory,只需将配置名称更改为 tcpEndpoint 即可。还可以在客户端配置文件中配置绑定,正如我在服务配置文件中所做的那样。

如果将此配置文件添加到图10 中所示的客户端控制台应用程序、标注创建 ServiceEndpoint 对象的代码并在构造每个 ChannelFactory 时指定端点名称,将得到相同的结果。

生成客户端代理


上述示例假定了客户端可以访问用于实现服务的同一接口定义。当 .NET 用于执行两端(在传统的 .NET 远程方案中)时这种假定是可以的,但它不一定适用于所有情况,当服务未通过 .NET Framework 实现时,这种假定就不成立。上述示例还假定客户端事先知道准确的端点详细信息,但这种假定也不一定始终成立。

当客户端没有访问此类信息的权限时,它们可以使用 WS-MetadataExchange 规范获得该信息。服务通过 WSDL 定义与客户端共享端点描述。大多数服务平台提供了用于从 WSDL 定义生成客户端代码的工具。WinFX SDK 为此目的提供了 SvcUtil.exe。

执行 SvcUtil.exe 时,您指定了 WSDL 定义的 URL,它将生成所需的 .NET 代码和配置元素,用以定义端点和服务端点使用的绑定。图 11 显示了通过 http://localhost:8080/echo 运行 SvcUtil.exe 的输出。请注意,它生成了两个文件:EchoService.cs 和 output.config。


图 11:SvcUtil.exe 输出


EchoService.cs 包含一个与服务实现的定义等效的 .NET 接口定义。Output.config 包含访问服务所需的客户端端点信息(与我刚才手写的内容类似)。您必须手动将 output.config 的内容与应用程序配置文件进行合并。这种情况下,可以使用上述示例中所使用的相同技术编写客户端代码,仅使用生成的接口和配置文件。

总之,WCF 客户端编程模型的服务边界非常明确。根据特定的服务端点创建一个类型通道,然后通过该通道发送消息。尽管它有助于强调面向服务的原则,但这可能使该级别的工作始终枯燥乏味。为了帮助您更好地工作,SvcUtil.exe 还生成一个代理类,可以完全隐藏 ChannelFactory 和 ServiceEndpoint 创建详细信息。如果打开 EchoService.cs,您将看到以下类定义:

public partial class EchoServiceProxy : 
System.ServiceModel.ClientBase<IEchoService>, IEchoService
{
public EchoServiceProxy()
    {
    }    
public EchoServiceProxy(string endpointConfigurationName) : 
base(endpointConfigurationName)
    {
    }
...

该代理类可以简化客户端应用程序代码。您需要做的只是实例化代理、指定端点配置的名称和进行方法调用。下面是一个示例:

using (EchoServiceProxy proxy = new EchoServiceProxy("IEchoService"))
{
//调用服务操作
Console.WriteLine("Invoking HTTP endpoint: {0}",
proxy.Echo("Hello, world"));
}
using (EchoServiceProxy proxy = new EchoServiceProxy("IEchoService1"))
{
//调用服务操作
Console.WriteLine("Invoking TCP endpoint: {0}",
proxy.Echo("Hello, world"));
}

生成的配置文件 (output.config) 定义了 IEchoService 和 IEchoService1 端点配置。

记录消息


开始使用 WCF 编程模型时,您可能会发现跟踪在客户端和服务之间传输的 SOAP 消息非常有用。Windows Communication Foundation 为消息日志记录提供内嵌式支持,可以在应用程序配置文件中将其打开。


图 12:SvcTraceViewer.exe


SvcConfigEditor 提供了一个“诊断”选项卡,您可以在此启用消息记录功能。启动消息记录并重新运行应用程序后,您将看到跟踪文件显示在指定的位置。WinFX SDK 还提供了 SvcTraceViewer.exe,用于查看跟踪文件中的信息(请参见图 12)。

小结


对于使用 .NET Framework 的开发人员来说,WCF 是分布式编程领域的一个新台阶。如果您当前正使用目前的任何 .NET 分布式技术建立系统,那么您应该开始关注 WCF 及其发展趋势。使用 WCF 编写所有与通信相关的以 .NET 为目标的代码只是一个时间问题。