How to: Write an Extension for the ServiceContractGenerator

This topic describes how to write an extension for the ServiceContractGenerator. This can be done by implementing the IOperationContractGenerationExtension interface on an operation behavior or implementing the IServiceContractGenerationExtension interface on a contract behavior. This topic shows how to implement the IServiceContractGenerationExtension interface on a contract behavior.

The ServiceContractGenerator generates service contracts, client types, and client configurations from ServiceEndpoint, ContractDescription, and Binding instances. Typically, you import ServiceEndpoint, ContractDescription, and Binding instances from service metadata and then use these instances to generate code to call the service. In this example, an IWsdlImportExtension implementation is used to process WSDL annotations and then add code generation extensions to the imported contracts to generate comments on the generated code.

To write an extension for the ServiceContractGenerator

  1. Implement IServiceContractGenerationExtension. To modify the generated service contract, use the ServiceContractGenerationContext instance passed into the GenerateContract(ServiceContractGenerationContext) method.

    public void GenerateContract(ServiceContractGenerationContext context)  
    {  
        Console.WriteLine("In generate contract.");  
        context.ContractType.Comments.AddRange(Formatter.FormatComments(commentText));  
    }  
    
  2. Implement IWsdlImportExtension on the same class. The ImportContract(WsdlImporter, WsdlContractConversionContext) method can process a specific WSDL extension (WSDL annotations in this case) by adding a code generation extension to the imported ContractDescription instance.

    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. Add the WSDL importer to your client configuration.

    <metadata>  
      <wsdlImporters>  
        <extension type="Microsoft.WCF.Documentation.WsdlDocumentationImporter, WsdlDocumentation" />  
      </wsdlImporters>  
    </metadata>  
    
  4. In the client code, create a MetadataExchangeClient and call GetMetadata.

    var mexClient = new MetadataExchangeClient(metadataAddress);  
    mexClient.ResolveMetadataReferences = true;  
    MetadataSet metaDocs = mexClient.GetMetadata();  
    
  5. Create a WsdlImporter and call ImportAllContracts.

    var importer = new WsdlImporter(metaDocs);
    System.Collections.ObjectModel.Collection<ContractDescription> contracts = importer.ImportAllContracts();  
    
  6. Create a ServiceContractGenerator and call GenerateServiceContractType for each contract.

    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) is called automatically for each contract behavior on a given contract that implements IServiceContractGenerationExtension. This method can then modify the ServiceContractGenerationContext passed in. In this example comments are added.

See also