如何:编写 ServiceContractGenerator 的扩展
本主题描述如何编写 ServiceContractGenerator 的扩展。这可以通过对操作行为实现 IOperationContractGenerationExtension 接口或者对协定行为实现 IServiceContractGenerationExtension 接口来完成。本主题演示如何对协定行为实现 IServiceContractGenerationExtension 接口。
ServiceContractGenerator 从 ServiceEndpoint、ContractDescription 和 Binding 实例生成服务协定、客户端类型和客户端配置。通常,需要先从服务元数据导入 ServiceEndpoint、ContractDescription 和 Binding 实例,然后使用这些实例生成调用服务的代码。在本示例中,IWsdlImportExtension 实现用于处理 WSDL 批注,然后将代码生成扩展添加到导入的协定中,以生成对已生成代码的注释。
编写 ServiceContractGenerator 的扩展
实现 IServiceContractGenerationExtension。若要修改已生成的服务协定,请使用传入 GenerateContract 方法的 ServiceContractGenerationContext 实例。
public void GenerateContract(ServiceContractGenerationContext context) { Console.WriteLine("In generate contract."); context.ContractType.Comments.AddRange(Formatter.FormatComments(commentText)); }
在同一个类上实现 IWsdlImportExtension。通过将代码生成扩展添加到导入的 ContractDescription 实例,ImportContract 方法可以处理特定的 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."); }
将 WSDL 导入程序添加到客户端配置中。
<metadata> <wsdlImporters> <extension type="Microsoft.WCF.Documentation.WsdlDocumentationImporter, WsdlDocumentation" /> </wsdlImporters> </metadata>
在客户端代码中,创建一个 MetadataExchangeClient 并调用 GetMetadata。
MetadataExchangeClient mexClient = new MetadataExchangeClient(metadataAddress); mexClient.ResolveMetadataReferences = true; MetadataSet metaDocs = mexClient.GetMetadata();
创建一个 WsdlImporter 并调用 ImportAllContracts。
WsdlImporter importer = new WsdlImporter(metaDocs); System.Collections.ObjectModel.Collection<ContractDescription> contracts = importer.ImportAllContracts();
创建一个 ServiceContractGenerator 并为每个协定调用 GenerateServiceContractType。
ServiceContractGenerator 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.");
会为实现 IServiceContractGenerationExtension 的给定协定上的每个协定行为自动调用 GenerateContract。然后,此方法可以修改传入的 ServiceContractGenerationContext。在本示例中,添加了注释。