如何:编写 ServiceContractGenerator 的扩展

本主题描述如何编写 ServiceContractGenerator 的扩展。 这可以通过对操作行为实现 IOperationContractGenerationExtension 接口或者对协定行为实现 IServiceContractGenerationExtension 接口来完成。 本主题演示如何对协定行为实现 IServiceContractGenerationExtension 接口。

ServiceContractGeneratorServiceEndpointContractDescriptionBinding 实例生成服务协定、客户端类型和客户端配置。 通常,需要先从服务元数据导入 ServiceEndpointContractDescriptionBinding 实例,然后使用这些实例生成调用服务的代码。 在本示例中,IWsdlImportExtension 实现用于处理 WSDL 批注,然后将代码生成扩展添加到导入的协定中,以生成对已生成代码的注释。

编写 ServiceContractGenerator 的扩展

  1. 实现 IServiceContractGenerationExtension。 若要修改已生成的服务协定,请使用传入 ServiceContractGenerationContext 方法的 GenerateContract(ServiceContractGenerationContext) 实例。

    public void GenerateContract(ServiceContractGenerationContext context)  
    {  
        Console.WriteLine("In generate contract.");  
        context.ContractType.Comments.AddRange(Formatter.FormatComments(commentText));  
    }  
    
  2. 在同一个类上实现 IWsdlImportExtension。 通过将代码生成扩展添加到导入的 ImportContract(WsdlImporter, WsdlContractConversionContext) 实例,ContractDescription 方法可以处理特定的 WSDL 扩展(此例中为 WSDL 批注)。

    public void ImportContract(WsdlImporter importer, WsdlContractConversionContext context)
    {
        // Contract documentation
        if (context.WsdlPortType.Documentation != null)
        {
            context.Contract.Behaviors.Add(new WsdlDocumentationImporter(context.WsdlPortType.Documentation));
        }
        // Operation documentation
        foreach (Operation operation in context.WsdlPortType.Operations)
        {
            if (operation.Documentation != null)
            {
                OperationDescription operationDescription = context.Contract.Operations.Find(operation.Name);
                if (operationDescription != null)
                {
                    operationDescription.Behaviors.Add(new WsdlDocumentationImporter(operation.Documentation));
                }
            }
        }
    }
    public void BeforeImport(ServiceDescriptionCollection wsdlDocuments, XmlSchemaSet xmlSchemas, ICollection<XmlElement> policy)
    {
        Console.WriteLine("BeforeImport called.");
    }
    
    public void ImportEndpoint(WsdlImporter importer, WsdlEndpointConversionContext context)
    {
        Console.WriteLine("ImportEndpoint called.");
    }
    
  3. 将 WSDL 导入程序添加到客户端配置中。

    <metadata>  
      <wsdlImporters>  
        <extension type="Microsoft.WCF.Documentation.WsdlDocumentationImporter, WsdlDocumentation" />  
      </wsdlImporters>  
    </metadata>  
    
  4. 在客户端代码中,创建一个 MetadataExchangeClient 并调用 GetMetadata

    var mexClient = new MetadataExchangeClient(metadataAddress);  
    mexClient.ResolveMetadataReferences = true;  
    MetadataSet metaDocs = mexClient.GetMetadata();  
    
  5. 创建一个 WsdlImporter 并调用 ImportAllContracts

    var importer = new WsdlImporter(metaDocs);
    System.Collections.ObjectModel.Collection<ContractDescription> contracts = importer.ImportAllContracts();  
    
  6. 创建一个 ServiceContractGenerator 并为每个协定调用 GenerateServiceContractType

    var generator = new ServiceContractGenerator();  
    foreach (ContractDescription contract in contracts)  
    {  
       generator.GenerateServiceContractType(contract);  
    }  
    if (generator.Errors.Count != 0)  
       throw new Exception("There were errors during code compilation.");  
    
  7. 会为实现 GenerateContract(ServiceContractGenerationContext) 的给定协定上的每个协定行为自动调用 IServiceContractGenerationExtension。 然后,此方法可以修改传入的 ServiceContractGenerationContext。 在此示例中,添加了注释。

另请参阅