了解生成的客户端代码Understanding Generated Client Code

ServiceModel Metadata Utility Tool (Svcutil.exe) 可生成用于生成客户端应用程序的客户端代码和客户端应用程序配置文件。The ServiceModel Metadata Utility Tool (Svcutil.exe) generates client code and a client application configuration file for use in building client applications. 本主题提供了有关标准服务协定方案的生成代码示例的教程。This topic provides a tour of generated code examples for standard service contract scenarios. 有关使用生成的代码生成客户端应用程序的详细信息, 请参阅WCF 客户端概述For more information about building a client application using the generated code, see WCF Client Overview.

概述Overview

如果使用 Visual Studio 生成项目的 Windows Communication Foundation (WCF) 客户端类型, 则通常不需要检查生成的客户端代码。If you use Visual Studio to generate Windows Communication Foundation (WCF) client types for your project, you typically do not need to examine the generated client code. 如果您并未使用为您执行相同服务的开发环境,您可以使用 Svcutil.exe 之类的工具来生成客户端代码,然后使用该代码开发客户端应用程序。If you are not using a development environment that performs the same services for you, you can use a tool such as Svcutil.exe to generate client code and then use that code to develop your client application.

由于 Svcutil.exe 具有许多可以修改生成的类型信息的选项,因此本主题并不对所有方案进行讨论。Because Svcutil.exe has a number of options that modify the generated type information, this topic does not discuss all scenarios. 但是,以下标准任务涉及查找生成的代码:However, the following standard tasks involve locating generated code:

  • 标识服务协定接口。Identifying service contract interfaces.

  • 标识 WCF 客户端类。Identifying the WCF client class.

  • 标识数据类型。Identifying data types.

  • 标识双工服务的回调协定。Identifying callback contracts for duplex services.

  • 标识帮助器服务协定通道接口。Identifying the helper service contract channel interface.

查找服务协定接口Finding Service Contract Interfaces

若要查找对服务协定建模的接口,请搜索使用 System.ServiceModel.ServiceContractAttribute 属性进行标记的接口。To locate the interfaces that model service contracts, search for interfaces that are marked with the System.ServiceModel.ServiceContractAttribute attribute. 由于存在其他属性 (Attribute) 和设置在该属性 (Attribute) 自身上的显式属性 (Property),因此要通过快速读取查找该属性 (Attribute) 通常并不容易。Often this attribute can be difficult to locate with a quick read due to the presence of other attributes and the explicit properties set on the attribute itself. 请记住,服务协定接口和客户端协定接口属于两种不同的类型。Remember that the service contract interface and the client contract interface are two different types. 下面的代码示例演示原始服务协定。The following code example shows the original service contract.

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

下面的代码示例演示 Svcutil.exe 生成的相同服务协定。The following code example shows the same service contract as generated by Svcutil.exe.

[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);
}

您可以使用生成的服务协定接口System.ServiceModel.ChannelFactory和类来创建 WCF 信道对象, 以调用服务操作。You can use the generated service contract interface along with the System.ServiceModel.ChannelFactory class to create a WCF channel object with which to invoke service operations. 有关详细信息,请参阅如何:使用 ChannelFactoryFor more information, see How to: Use the ChannelFactory.

查找 WCF 客户端类Finding WCF Client Classes

若要查找实现您要使用的服务协定的 WCF 客户端类, 请搜索的扩展名System.ServiceModel.ClientBase<TChannel>, 其中类型参数为您先前找到的、扩展该接口的服务协定接口。To locate the WCF client class that implements the service contract you want to use, search for an extension of System.ServiceModel.ClientBase<TChannel>, where the type parameter is the service contract interface that you previously located and that extends that interface. 下面的代码示例演示类型为 ClientBase<TChannel>ISampleService类。The following code example shows the ClientBase<TChannel> class of type ISampleService.

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class SampleServiceClient : System.ServiceModel.ClientBase<ISampleService>, ISampleService
{

    public SampleServiceClient()
    {
    }

    public SampleServiceClient(string endpointConfigurationName)
        :
            base(endpointConfigurationName)
    {
    }

    public SampleServiceClient(string endpointConfigurationName, string remoteAddress)
        :
            base(endpointConfigurationName, remoteAddress)
    {
    }

    public SampleServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress)
        :
            base(endpointConfigurationName, remoteAddress)
    {
    }

    public SampleServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress)
        :
            base(binding, remoteAddress)
    {
    }
    public string SampleMethod(string msg)
    {
        return base.Channel.SampleMethod(msg);
    }
}

可以通过创建新实例并调用它实现的方法来使用此 WCF 客户端类。You can use this WCF client class by creating a new instance of it and calling the methods it implements. 这些方法调用服务操作,可设计和配置该服务操作以进行交互。Those methods invoke the service operation with which it is designed and configured to interact. 有关详细信息, 请参阅WCF 客户端概述For more information, see WCF Client Overview.

备注

SvcUtil.exe 在生成 WCF 客户端类时会将一个 DebuggerStepThroughAttribute 添加到该客户端类,以防止调试器逐步调试该 WCF 客户端类。When SvcUtil.exe generates a WCF client class, it adds a DebuggerStepThroughAttribute to the client class that prevents debuggers from stepping through the WCF client class.

查找数据类型Finding Data Types

若要在生成的代码中查找数据类型,最简单的方法就是标识协定中指定的类型名称并搜索该类型声明的代码。To locate data types in the generated code, the most basic mechanism is to identify the type name specified in a contract and search the code for that type declaration. 例如,下面的协定指定 SampleMethod 可以返回 microsoft.wcf.documentation.SampleFault类型的 SOAP 错误。For example, the following contract specifies that the SampleMethod can return a SOAP fault of type microsoft.wcf.documentation.SampleFault.

[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);

搜索 SampleFault 查找下面的类型声明。Searching for SampleFault locates the following type declaration.

[assembly: System.Runtime.Serialization.ContractNamespaceAttribute(
  "http://microsoft.wcf.documentation",
  ClrNamespace = "microsoft.wcf.documentation"
)]
namespace microsoft.wcf.documentation
{
    using System.Runtime.Serialization;

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
    [System.Runtime.Serialization.DataContractAttribute()]
    public partial class SampleFault : object, System.Runtime.Serialization.IExtensibleDataObject
    {
        private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
        private string FaultMessageField;

        public System.Runtime.Serialization.ExtensionDataObject ExtensionData
        {
            get
            {
                return this.extensionDataField;
            }
            set
            {
                this.extensionDataField = value;
            }
        }

        [System.Runtime.Serialization.DataMemberAttribute()]
        public string FaultMessage
        {
            get
            {
                return this.FaultMessageField;
            }
            set
            {
                this.FaultMessageField = value;
            }
        }
    }
}

在本示例中,数据类型为客户端上的特定异常(一个 FaultException<TDetail> ,其中详细信息类型为 microsoft.wcf.documentation.SampleFault)引发的详细信息类型。In this case the data type is the detail type thrown by a specific exception on the client, a FaultException<TDetail> where the detail type parameter is microsoft.wcf.documentation.SampleFault. 有关数据类型的详细信息, 请参阅在服务协定中指定数据传输For more information about data types, see Specifying Data Transfer in Service Contracts. 有关在客户端中处理异常的详细信息, 请参阅发送和接收错误For more information about handling exceptions in clients, see Sending and Receiving Faults.

查找双工服务的回调协定Finding Callback Contracts for Duplex Services

如果要查找协定接口为其 ServiceContractAttribute.CallbackContract 属性指定一个值的服务协定,则该协定指定一个双工协定。If you locate a service contract for which the contract interface specifies a value for the ServiceContractAttribute.CallbackContract property, then that contract specifies a duplex contract. 双工协定要求客户端应用程序创建一个回调类,该类实现回调协定并将此类的一个实例传递给 System.ServiceModel.DuplexClientBase<TChannel> 或用来与服务进行通信的 System.ServiceModel.DuplexChannelFactory<TChannel>Duplex contracts require the client application to create a callback class that implements the callback contract and pass an instance of that class to the System.ServiceModel.DuplexClientBase<TChannel> or System.ServiceModel.DuplexChannelFactory<TChannel> used to communicate with the service. 有关双工客户端的详细信息, 请参阅如何:使用双工协定访问服务。For more information about duplex clients, see How to: Access Services with a Duplex Contract.

下面的协定指定一个 SampleDuplexHelloCallback类型的回调协定。The following contract specifies a callback contract of type SampleDuplexHelloCallback.

[System.ServiceModel.ServiceContractAttribute(
  Namespace="http://microsoft.wcf.documentation", 
  ConfigurationName="SampleDuplexHello", 
  CallbackContract=typeof(SampleDuplexHelloCallback), 
  SessionMode=System.ServiceModel.SessionMode.Required
)]
public interface SampleDuplexHello
{
  [System.ServiceModel.OperationContractAttribute(
      IsOneWay=true, 
      Action="http://microsoft.wcf.documentation/SampleDuplexHello/Hello"
    )]
    void Hello(string greeting);
  }
    <System.ServiceModel.OperationContractAttribute(IsOneWay:=True, _
        Action:="http://microsoft.wcf.documentation/SampleDuplexHello/Hello")> _
    Sub Hello(ByVal greeting As String)
End Interface 'SampleDuplexHello

搜索该回调协定定位下面的接口,客户端应用程序必须实现该接口。Searching for that callback contract locates the following interface that the client application must implement.

  [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface SampleDuplexHelloCallback
{
  [System.ServiceModel.OperationContractAttribute(
      IsOneWay=true, 
      Action="http://microsoft.wcf.documentation/SampleDuplexHello/Reply"
    )]
    void Reply(string responseToGreeting);
  }
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")>  _
Public Interface SampleDuplexHelloCallback
    <System.ServiceModel.OperationContractAttribute( _
        IsOneWay:=True, _
        Action:="http://microsoft.wcf.documentation/SampleDuplexHello/Reply")> _
    Sub Reply(ByVal responseToGreeting As String)
End Interface 'SampleDuplexHelloCallback

查找服务协定通道接口Finding Service Contract Channel Interfaces

ChannelFactory 类与服务协定接口一起使用时,您必须强制转换到 System.ServiceModel.IClientChannel 接口以显式打开、关闭或中止通道。When using the ChannelFactory class with a service contract interface, you must cast to the System.ServiceModel.IClientChannel interface to explicitly open, close, or abort the channel. 为便于操作,Svcutil.exe 工具还生成一个帮助器接口,该接口可同时实现服务协定接口和 IClientChannel ,以使您无需进行强制转换就能够与客户端通道基础结构进行交互。To make it easier to work with, the Svcutil.exe tool also generates a helper interface that implements both the service contract interface and IClientChannel to enable you to interact with the client channel infrastructure without having to cast. 下面的代码演示实现上述服务协定的帮助器客户端通道的定义。The following code shows the definition of a helper client channel that implements the preceding service contract.

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

请参阅See also