方法 : カスタム WSDL をエクスポートする

ここでは、カスタム WSDL 情報をエクスポートする方法について説明します。そのために、サービスによって生成された WSDL にカスタム情報を追加する WsdlDocumentationAttribute という名前の新しいコード属性を定義します。

カスタム WSDL 情報をエクスポートするには

  1. IWsdlExportExtension インターフェイスを実装します。このインターフェイスは、IOperationBehaviorIContractBehavior、または IEndpointBehavior インターフェイスを実装するクラスに実装できます。また、BindingElement から派生したクラスに実装することもできます。このサンプルでは、IContractBehavior を実装する属性クラスに IWsdlExportExtension を実装します。

  2. IWsdlExportExtension は、ExportEndpoint メソッドと ExportContract メソッドを定義します。これらのメソッドを使用すると、WsdlContractConversionContext を変更したり、情報を追加したりできます (変更と追加の両方を行うこともできます)。このサンプルは、ExportContract メソッドで OperationDescription オブジェクトのコレクションを取得し、そのコレクションを反復処理して WsdlDocumentationAttribute が存在するかどうかをチェックします。見つかった場合は、属性に関連付けられたテキストが抽出され、summary 要素が生成され、その summary 要素が操作の DocumentationElement に追加されます。

            public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
    {
                Console.WriteLine("Inside ExportContract");
    if (context.Contract != null)
    {
                    // Set the document element; if this is not done first, there is no XmlElement in the 
                    // DocumentElement property.
                    context.WsdlPortType.Documentation = string.Empty; 
                    // Contract comments.
                    XmlDocument owner = context.WsdlPortType.DocumentationElement.OwnerDocument;
                    XmlElement summaryElement = Formatter.CreateSummaryElement(owner, this.Text); 
                    context.WsdlPortType.DocumentationElement.AppendChild(summaryElement);
    
                    foreach (OperationDescription op in context.Contract.Operations)
                    {
                        Operation operation = context.GetOperation(op);
                        object[] opAttrs = op.SyncMethod.GetCustomAttributes(typeof(WsdlDocumentationAttribute), false);
                        if (opAttrs.Length == 1)
                        {
                            string opComment = ((WsdlDocumentationAttribute)opAttrs[0]).Text;
    
                            // This.Text returns the string for the operation-level attributes.
                            // Set the doc element; if this is not done first, there is no XmlElement in the 
                            // DocumentElement property.
                            operation.Documentation = String.Empty;
    
                            XmlDocument opOwner = operation.DocumentationElement.OwnerDocument;
                            XmlElement newSummaryElement = Formatter.CreateSummaryElement(opOwner, opComment);
                            operation.DocumentationElement.AppendChild(newSummaryElement);
                        }
                    }
                }
    

WsdlDocumentationAttribute クラスの完全な実装を次のコード例に示します。

public class WsdlDocumentationAttribute : Attribute, IContractBehavior, IWsdlExportExtension
{
string text;
       XmlElement customWsdlDocElement = null;
public WsdlDocumentationAttribute(string text)
{ this.text = text;}

       public WsdlDocumentationAttribute(XmlElement wsdlDocElement)
        { this.customWsdlDocElement = wsdlDocElement; }

        public XmlElement WsdlDocElement
        {
            get { return this.customWsdlDocElement; }
            set { this.customWsdlDocElement = value; }
        }
       public string Text
{
get { return this.text; }
set { this.text = value; }
}

     public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
{
          Console.WriteLine("Inside ExportContract");
if (context.Contract != null)
{
                // Set the document element; if this is not done first, there is no XmlElement in the 
                // DocumentElement property.
                context.WsdlPortType.Documentation = string.Empty; 
                // Contract comments.
                XmlDocument owner = context.WsdlPortType.DocumentationElement.OwnerDocument;
                XmlElement summaryElement = Formatter.CreateSummaryElement(owner, this.Text); 
                context.WsdlPortType.DocumentationElement.AppendChild(summaryElement);
   
                foreach (OperationDescription op in context.Contract.Operations)
                {
                    Operation operation = context.GetOperation(op);
                    object[] opAttrs = op.SyncMethod.GetCustomAttributes(typeof(WsdlDocumentationAttribute), false);
                    if (opAttrs.Length == 1)
                    {
                        string opComment = ((WsdlDocumentationAttribute)opAttrs[0]).Text;

                        // This.Text returns the string for the operation-level attributes.
                        // Set the document element; if this is not done first, there is no XmlElement in the 
                        // DocumentElement property.
                        operation.Documentation = String.Empty;

                        XmlDocument opOwner = operation.DocumentationElement.OwnerDocument;
                        XmlElement newSummaryElement = Formatter.CreateSummaryElement(opOwner, opComment);
                        operation.DocumentationElement.AppendChild(newSummaryElement);
                    }
                }
            }
        }

public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context) 
        {
            Console.WriteLine("ExportEndpoint called.");
        }

        public void AddBindingParameters(ContractDescription description, ServiceEndpoint endpoint, BindingParameterCollection parameters)
        { return; }

        public void ApplyClientBehavior(ContractDescription description, ServiceEndpoint endpoint, ClientRuntime client)
        { return; }

        public void ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, DispatchRuntime dispatch)
        { return; }

        public void Validate(ContractDescription description, ServiceEndpoint endpoint) { return; }
    }

  public class Formatter
  {

#region Utility Functions

    public static XmlElement CreateSummaryElement(XmlDocument owningDoc, string text)
    {
      XmlElement summaryElement = owningDoc.CreateElement("summary");
      summaryElement.InnerText = text;
      return summaryElement;
    }

public static CodeCommentStatementCollection FormatComments(string text)
{
      /*
       * Note that in Visual C# the XML comment format absorbs a 
       * documentation element with a line break in the middle. This sample
       * could take an XmlElement and create code comments in which 
       * the element never had a line break in it.
      */

      CodeCommentStatementCollection collection = new CodeCommentStatementCollection();
collection.Add(new CodeCommentStatement("From WsdlDocumentation:", true));
collection.Add(new CodeCommentStatement(String.Empty, true));

foreach (string line in WordWrap(text, 80))
{
collection.Add(new CodeCommentStatement(line, true));
}

collection.Add(new CodeCommentStatement(String.Empty, true));
return collection;
}

public static Collection<string> WordWrap(string text, int columnWidth)
{
Collection<string> lines = new Collection<string>();
System.Text.StringBuilder builder = new System.Text.StringBuilder();

string[] words = text.Split(' ');
foreach (string word in words)
{
if ((builder.Length > 0) && ((builder.Length + word.Length + 1) > columnWidth))
{
lines.Add(builder.ToString());
builder = new System.Text.StringBuilder();
}
builder.Append(word);
builder.Append(' ');
}
lines.Add(builder.ToString());

return lines;
}

#endregion  
  
    public static XmlElement CreateReturnsElement(XmlDocument owner, string p)
    {
      XmlElement returnsElement = owner.CreateElement("returns");
      returnsElement.InnerText = p;
      return returnsElement;
    }
  }

参照

概念

メタデータ