Procedura: esportare informazioni WSDL personalizzate
In questo argomento viene illustrato come esportare informazioni WSDL personalizzate. A tale scopo è necessario definire un nuovo attributo di codice denominato WsdlDocumentationAttribute
che consente di aggiungere informazioni personalizzate nel codice WSDL generato dal servizio.
Per esportare informazioni WSDL personalizzate
Implementare l'interfaccia IWsdlExportExtension. Questa interfaccia può essere implementata in una classe che implementa una delle interfacce seguenti: IOperationBehavior, IContractBehavior o IEndpointBehavior. Può inoltre essere implementata in una classe derivata della classe BindingElement. In questo esempio l'interfaccia IWsdlExportExtension viene implementata in una classe di attributo che implementa l'interfaccia IContractBehavior.
L'interfaccia IWsdlExportExtension definisce due metodi: ExportEndpoint e ExportContract. Questi metodi consentono di modificare e/o aggiungere informazioni aggiuntive nel contesto WsdlContractConversionContext. In questo esempio il metodo ExportContract viene utilizzato per recuperare un insieme di oggetti OperationDescription. All'interno di questo insieme viene quindi eseguita una ricerca per verificare la presenza di un attributo
WsdlDocumentationAttribute
. Se la ricerca ha esito positivo, il sistema estrae il testo associato all'attributo trovato, genera un elemento riassuntivo e quindi aggiunge tale elemento all'elementoDocumentationElement
dell'operazione.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); } } }
Esempio
Nell'esempio di codice seguente viene illustrata l'implementazione completa della classe 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;
}
}