Condividi tramite


Passaggio 6: Implementare il gestore per la risoluzione di metadati per Echo Adapter

Passaggio 6 di 9

Tempo da completare: 45 minuti

In questo passaggio si implementa l'interfaccia per risolvere l'operazione Microsoft.ServiceModel.Channels.Common.IMetadataResolverHandler e digitare metadati per l'adapter echo. Indipendentemente dalla funzionalità della scheda, è necessario implementare questa interfaccia. La Creazione guidata adapter genera automaticamente la classe derivata denominata EchoAdapterMetadataResolverHandler per l'utente.

Nella sezione seguente si aggiorna la classe EchoAdapterMetadataResolverHandler per ottenere una migliore comprensione su come implementare questa interfaccia. Al termine di questo passaggio, è disponibile un gestore di risoluzione dei metadati funzionante per l'adapter echo.

Prerequisiti

Prima di iniziare questo passaggio, è necessario aver completato correttamente il passaggio 5: Implementare il gestore ricerca metadati per l'adapter Echo. È anche necessario comprendere le classi di operazione e tipo seguenti:

  • Microsoft.ServiceModel.Channels.Common.ParameterizedOperationMetadata

  • Microsoft.ServiceModel.Channels.Common.OperationMetadata

  • Microsoft.ServiceModel.Channels.Common.OperationParameter

  • Microsoft.ServiceModel.Channels.Common.OperationResult

  • Microsoft.ServiceModel.Channels.Common.TypeMetadata

  • Microsoft.ServiceModel.Channels.Common.StructuredTypeMetadata

  • Microsoft.ServiceModel.Channels.Common.TypeMember

  • Microsoft.ServiceModel.Channels.Common.SimpleQualifiedType

  • Microsoft.ServiceModel.Channels.Common.ComplexQualifiedType

Interfaccia IMetadataResolverHandler

public interface IMetadataResolverHandler : IConnectionHandler, IDisposable  
  {  
      bool IsOperationMetadataValid(string operationId, DateTime lastUpdatedTimestamp, TimeSpan timeout);        
      bool IsTypeMetadataValid(string typeId, DateTime lastUpdatedTimestamp, TimeSpan timeout);  
      OperationMetadata ResolveOperationMetadata(string operationId, TimeSpan timeout, out TypeMetadataCollection extraTypeMetadataResolved);  
      TypeMetadata ResolveTypeMetadata(string typeId, TimeSpan timeout, out TypeMetadataCollection extraTypeMetadataResolved);  
  }  

La tabella seguente descrive le operazioni di ogni metodo:

Nome metodo Descrizione
IsOperationMetadataValid Restituisce un valore true se i metadati del tipo non sono stati modificati dopo la data e l'ora specificata
IsTypeMetadataValid Restituisce un valore booleano che indica se i metadati di tipo specificati sono validi.
ResolveOperationMetadata Risolve un ID operazione in corrispondenza del corrispondente Microsoft.ServiceModel.Channels.Common.OperationMetadata
ResolveTypeMetadata Risolve un tipo di metadati specificatoId a un oggetto corrispondente Microsoft.ServiceModel.Channels.Common.TypeMetadata.

Per implementare il metodo IsOperationMetadataValid

  1. In Esplora soluzioni fare doppio clic sul file EchoAdapterMetadataResolverHandler.cs.

  2. Nell'editor di Visual Studio fare clic con il pulsante destro del mouse in un punto qualsiasi all'interno dell'editor, nel menu di scelta rapida, scegliere Struttura e quindi fare clic su Arresta struttura.

  3. Nell'editor di Visual Studio trovare il metodo IsOperationMetadataValid , all'interno di questo metodo, sostituire l'esistente con l'istruzione singola seguente per indicare che tutti i metadati dell'operazione specificati sono validi.

    return true;  
    

Per implementare il metodo IsTypeMetadataValid

  • Nell'editor di Visual Studio trovare il metodo IsTypeMetadataValid , all'interno di questo metodo, sostituire l'esistente con l'istruzione singola seguente per indicare che ogni metadati di tipo specificato è valido.

    return true;  
    

Per implementare il metodo ResolveOperationMetadata

  1. Nell'editor di Visual Studio trovare il metodo ResolveOperationMetadata , all'interno di questo metodo, sostituire l'esistente con il seguente per risolvere l'operazione OnReceiveEcho, void OnReceiveEcho(percorso Uri, long fileLength).

    extraTypeMetadataResolved = null;  
    switch( operationId )  
    {  
        case "Echo/OnReceiveEcho":  
            ParameterizedOperationMetadata om = new ParameterizedOperationMetadata(operationId, "OnReceiveEcho");  
            om.OriginalName = "lobNotification";  
            om.Description = "This operation echoes the location and length of a file dropped in the specified file system.";  
            om.OperationGroup = "EchoInboundContract";  
            om.OperationNamespace = EchoAdapter.SERVICENAMESPACE;  
            // syntax: void OnReceiveEcho(Uri path, long fileLength)  
            OperationParameter parmPath = new OperationParameter("path", OperationParameterDirection.In, QualifiedType.UriType, false);  
            parmPath.Description = "Absolute path of the file";  
            OperationParameter parmLength = new OperationParameter("length", OperationParameterDirection.In, QualifiedType.LongType, false);  
            parmLength.Description = "Length of the file received in this location.";  
            om.Parameters.Add(parmPath);  
            om.Parameters.Add(parmLength);  
            om.OperationResult = OperationResult.Empty;  
            return om;  
    
  2. Continuare a aggiungere quanto segue per risolvere l'operazione Echo/EchoStrings, string[] EchoStrings(string data).

    case "Echo/EchoStrings":  
        om = new ParameterizedOperationMetadata(operationId, "EchoStrings");  
        om.OriginalName = "lobEchoStrings";  
        om.Description = "This operation echoes the incoming string COUNT number of times in a string array.";  
        om.OperationGroup = "EchoOutboundContract";  
        om.OperationNamespace = EchoAdapter.SERVICENAMESPACE;  
        // syntax: string[] EchoStrings(string data)  
        OperationParameter parmData = new OperationParameter("data", OperationParameterDirection.In, QualifiedType.StringType, false);  
        parmData.Description = "Input string";  
        om.Parameters.Add(parmData);  
        om.OperationResult = new OperationResult(QualifiedType.StringType, true);  
        return om;  
    
  3. Continuare a aggiungere la logica seguente per risolvere l'operazione Echo/EchoStrings, stringa[] EchoStrings(string data).

    case "Echo/EchoGreetings":  
        om = new ParameterizedOperationMetadata(operationId, "EchoGreetings");  
        om.OriginalName = "lobEchoGreetings";  
        om.Description = "This operation echoes the incoming Greeting object COUNT number of times in an array of type Greeting.";  
        om.OperationGroup = "EchoOutboundContract";  
        om.OperationNamespace = EchoAdapter.SERVICENAMESPACE;  
        // syntax: Greeting[] EchoGreetings(Greeting greeting)  
        ComplexQualifiedType cqtGreeting = new ComplexQualifiedType("Types/GreetingType");  
        OperationParameter parmGreeting = new OperationParameter("greeting", OperationParameterDirection.In, cqtGreeting, false);  
        parmGreeting.Description = "Input greeting";  
        om.Parameters.Add(parmGreeting);  
        om.OperationResult = new OperationResult(cqtGreeting, true);  
        return om;  
    
  4. Continuare a aggiungere la logica seguente per risolvere l'operazione CustomGreeting EchoCustomGreetingFromFile(Uri greetingInstancePath).

    case "Echo/EchoCustomGreetingFromFile":  
        om = new ParameterizedOperationMetadata(operationId, "EchoCustomGreetingFromFile");  
        om.OriginalName = "lobEchoGreetingUsePredefinedMetadata";  
        om.Description = "This operation echoes the incoming Greeting object COUNT number of times in an array of type Greeting.  The Greeting type metadata is created using predefined XSD file.";  
        om.OperationGroup = "EchoOutboundContract";  
        om.OperationNamespace = EchoAdapter.SERVICENAMESPACE;  
        OperationParameter parmGreetingInstancePath = new OperationParameter("greetingInstancePath", OperationParameterDirection.In, QualifiedType.UriType, false);  
        om.Parameters.Add(parmGreetingInstancePath);  
        ComplexQualifiedType cqtGreetingXsd = new ComplexQualifiedType("Types/CustomGreetingFromXsdType");  
        om.OperationResult = new OperationResult(cqtGreetingXsd, false);  
    
        // resolve extra typemetadata here  
        extraTypeMetadataResolved = new TypeMetadataCollection();  
    
        // use a predefined schema to generate metadata for this type  
        CustomGreetingTypeMetadata tmGreetingXsd = new CustomGreetingTypeMetadata("Types/CustomGreetingFromXsdType", "CustomGreeting");  
        extraTypeMetadataResolved.Add(tmGreetingXsd);                   
        return om;  
    
    
  5. Continuare a aggiungere quanto segue per gestire il caso predefinito.

        default:  
            throw new AdapterException("Cannot resolve metadata for operation identifier " + operationId);  
    }  
    

Per implementare il metodo ResolveTypeMetadata

  • Nell'editor di Visual Studio trovare il metodo ResolveTypeMetadata , all'interno di questo metodo, sostituire l'esistente con il seguente per restituire un Microsoft.ServiceModel.Channels.Common.TypeMetadata oggetto.

    extraTypeMetadataResolved = null;  
    string typeNamespaceForGreeting = EchoAdapter.SERVICENAMESPACE + "/Types";  
    switch (typeId)  
    {  
        case "Types/GreetingType":  
            StructuredTypeMetadata tmGreeting = new StructuredTypeMetadata(typeId, "Greeting");  
            tmGreeting.TypeNamespace = typeNamespaceForGreeting;  
            tmGreeting.Members.Add(new TypeMember("id", QualifiedType.GuidType, false));  
            tmGreeting.Members.Add(new TypeMember("sentDateTime", QualifiedType.DateTimeType, false));  
            ComplexQualifiedType cqtName = new ComplexQualifiedType("Types/NameType");  
            tmGreeting.Members.Add(new TypeMember("name", cqtName, false));  
            tmGreeting.Members.Add(new TypeMember("greetingText", QualifiedType.StringType, false));  
            return tmGreeting;  
    
        case "Types/NameType":  
            StructuredTypeMetadata tmName = new StructuredTypeMetadata(typeId, "Name");  
            tmName.TypeNamespace = typeNamespaceForGreeting;  
            ComplexQualifiedType cqtSalutation = new ComplexQualifiedType("Types/SalutationType");  
            tmName.Members.Add(new TypeMember("salutation", cqtSalutation, false));  
            tmName.Members.Add(new TypeMember("firstName", QualifiedType.StringType, false));  
            tmName.Members.Add(new TypeMember("middleName", QualifiedType.StringType, false));  
            tmName.Members.Add(new TypeMember("lastName", QualifiedType.StringType, false));  
            return tmName;  
    
        case "Types/SalutationType":  
            EnumTypeMetadata tmSalutation = new EnumTypeMetadata(typeId, "Salutation", new string[] { "Mr.", "Mrs.", "Dr.", "Ms.", "Miss" });  
            tmSalutation.TypeNamespace = typeNamespaceForGreeting;  
            return tmSalutation;  
    
        default:  
            throw new AdapterException("Cannot resolve metadata for type identifier " + typeId);  
    }  
    
    

Per definire la classe di metadati del tipo di saluto personalizzata

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto Echo Adapter, scegliere Aggiungi e quindi fare clic su Nuovo elemento.

  2. Nella finestra di dialogo Aggiungi nuovo elemento fare clic su Classe in Modelli.

  3. Nella casella di testo Nome digitare CustomGreetingTypeMetadata.

  4. Fare clic su Aggiungi.

  5. Nell'editor di Visual Studio sostituire il codice esistente con quanto segue:

    using System;  
    using System.Collections.Generic;  
    using System.Text;  
    using Microsoft.ServiceModel.Channels.Common;  
    using System.Xml;  
    using System.Xml.Schema;  
    using System.IO;  
    
    namespace Microsoft.Adapters.Samples.EchoV2  
    {  
        public class CustomGreetingTypeMetadata : TypeMetadata  
        {  
            private const string CONST_METADATA_FILE_NAME = "Microsoft.Adapters.Samples.EchoV2.CustomGreeting.xsd";  
    
            public CustomGreetingTypeMetadata(string typeId, string typeName)  
                : base(typeId, typeName)  
            {  
                this.TypeNamespace = EchoAdapter.SERVICENAMESPACE + "/PreDefinedTypes";  
                this.Description = " ";  
                this.CanUseCommonCache = true;  
                // if the nillable is not set to true, the generated proxy wraps the operation  
                // with request and response objects  
                this.IsNillable = true;  
            }  
    
            /// <summary>  
            /// Override the base ExportXmlSchema to provide own   
            /// custom XML Schema  
            /// </summary>  
            /// <param name="schemaExportContext"></param>  
            /// <param name="metadataLookup"></param>  
            /// <param name="timeout"></param>  
            public override void ExportXmlSchema(XmlSchemaExportContext schemaExportContext, MetadataLookup metadataLookup, TimeSpan timeout)  
            {  
                if (schemaExportContext == null)  
                {  
                    throw new AdapterException("Schema export context is null.");  
                }  
                // Read in XML Schema file or create XmlSchema object yourself  
                Stream predefinedXsdFile = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(CONST_METADATA_FILE_NAME);  
                XmlReader reader = XmlReader.Create(predefinedXsdFile);  
                XmlSchema schema = XmlSchema.Read(reader, null);  
                if (!IsComplexTypeAlreadyDefined(schemaExportContext.SchemaSet, schema))  
                {  
                    schemaExportContext.SchemaSet.Add(schema);  
                    if (!schemaExportContext.NamespacePrefixSet.ContainsKey(this.TypeNamespace))  
                    {  
                        schemaExportContext.NamespacePrefixSet.Add(this.TypeNamespace, getUniqueNamespacePrefix(schemaExportContext, 0));  
                    }  
                }  
                reader.Close();  
            }  
    
            /// <summary>  
            /// A default value cannot be set for this type metadata.  
            /// </summary>  
            public override bool CanSetDefaultValue  
            {  
                get { return false; }  
            }  
    
            /// <summary>  
            /// Helper function to see if the schema is already defined in the   
            /// XmlSchemaSet.  
            /// </summary>  
            /// <param name="oldschemaset"></param>  
            /// <param name="newschema"></param>  
            /// <returns></returns>  
            public static bool IsComplexTypeAlreadyDefined(XmlSchemaSet oldschemaset, XmlSchema newschema)  
            {  
                // ensure correct namespace was defined in the passed-in schema  
                foreach (XmlSchema schema in oldschemaset.Schemas(newschema.TargetNamespace))  
                {  
                    foreach (XmlSchemaObject newschemaObject in newschema.Items)  
                    {  
                        if (newschemaObject is XmlSchemaComplexType)  
                        {  
                            //check for the definition of complex type in the schemaset             
                            foreach (XmlSchemaObject schemaObject in schema.Items)  
                            {  
                                XmlSchemaComplexType complexType = schemaObject as XmlSchemaComplexType;  
                                // Definition of this Complex Type already exists  
                                if (complexType != null && String.Compare(complexType.Name, ((XmlSchemaComplexType)newschemaObject).Name, false, System.Globalization.CultureInfo.InvariantCulture) == 0)  
                                    return true;  
                            }  
                        }  
                    }  
                }  
                return false;  
            }  
    
            /// <summary>  
            /// Helper function to generate a unique namespace prefix  
            /// </summary>  
            /// <param name="schemaExportContext"></param>  
            /// <param name="startSuffix"></param>  
            /// <returns></returns>  
            private string getUniqueNamespacePrefix(XmlSchemaExportContext schemaExportContext, int startSuffix)  
            {  
                string defaultPrefix = "ns";  
                string val = defaultPrefix + startSuffix;  
                if (schemaExportContext.NamespacePrefixSet.ContainsValue(val))  
                {  
                    return getUniqueNamespacePrefix(schemaExportContext, ++startSuffix);  
                }  
                else  
                {  
                    return val;  
                }  
            }  
        }  
    }  
    
  6. In Visual Studio fare clic su Salva tutto dal menu File.

Per creare la definizione di XML Schema di saluto personalizzato

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto Echo Adapter, scegliere Aggiungi e quindi fare clic su Nuovo elemento.

  2. Nella finestra di dialogo Aggiungi nuovo elemento , in Modelli fare clic su XML Schema.

  3. Nella casella di testo Nome digitare CustomGreeting.

  4. Fare clic su Aggiungi.

  5. In Esplora soluzioni fare clic con il pulsante destro del mouse sul file CustomGreeting.xsd e scegliere Visualizza codice.

  6. Nell'editor di Visual Studio iniziare sostituendo il codice esistente con il codice seguente che inizia la definizione dello schema CustomGreeting:

    <?xml version="1.0" encoding="utf-8" ?>   
    <xs:schema id="XMLSchema1"   
                      targetNamespace="http://tempuri.org/XMLSchema1.xsd"  
                      elementFormDefault="qualified"  
                      xmlns="http://tempuri.org/XMLSchema1.xsd"  
                      xmlns:mstns="http://tempuri.org/XMLSchema1.xsd"  
                      xmlns:xs="http://www.w3.org/2001/XMLSchema">  
    </xs:schema>  
    

    con il codice seguente che inizia la definizione dello schema CustomGreeting:

    <?xml version="1.0" encoding="utf-16"?>  
    <xsd:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns="echov2://microsoft.adapters.samples.echov2/PreDefinedTypes" elementFormDefault="qualified" targetNamespace="echov2://microsoft.adapters.samples.echov2/PreDefinedTypes" xmlns:xsd ="http://www.w3.org/2001/XMLSchema">  
    
  7. Aggiungere quanto segue per definire l'elemento CustomGreeting:

    <xsd:element name="greeting" type="CustomGreeting" />  
    
  8. Aggiungere ora la definizione del tipo complesso CustomGreeting:

    <xsd:complexType name="CustomGreeting">  
      <xsd:sequence>  
        <xsd:element name="address" type="UsAddress" />  
        <xsd:element name="greetingText" type="xsd:string" />  
      </xsd:sequence>  
    </xsd:complexType>  
    
  9. Continuare la definizione dello schema CustomGreeting aggiungendo il tipo complesso UsAddress:

    <xsd:complexType name="UsAddress">  
      <xsd:sequence>  
        <xsd:element minOccurs="1" maxOccurs="1" name="street1" nillable="true" type="xsd:string" />  
        <xsd:element minOccurs="0" maxOccurs="1" name="street2" type="xsd:string" />  
        <xsd:element minOccurs="1" maxOccurs="1" name="city" type="xsd:string" />  
        <xsd:element minOccurs="1" maxOccurs="1" name="state" type="xsd:string" />  
        <xsd:element name="zip" type="PostalCode" />  
      </xsd:sequence>  
    </xsd:complexType>  
    
  10. Completare la definizione dello schema CustomGreeting aggiungendo il tipo semplice PostalCode e il tag di chiusura per lo schema:

      <xsd:simpleType name="PostalCode">  
        <xsd:restriction base="xsd:positiveInteger">  
          <xsd:pattern value="\d{5}" />  
        </xsd:restriction>  
      </xsd:simpleType>  
    </xsd:schema>  
    
  11. Aggiornare ora l'azione di compilazione per questo file in modo che venga considerata come risorsa incorporata. A tale scopo, nel riquadro della soluzione di Visual Studio fare clic con il pulsante destro del mouse sul file e scegliere Proprietà. Modificare l'azione di compilazione da None a Risorsa incorporata.

  12. In Visual Studio fare clic su Salva tutto dal menu File.

Nota

Il lavoro è stato salvato. È possibile chiudere Visual Studio in modo sicuro in questo momento o passare al passaggio successivo, passaggio 7: Implementare il gestore in uscita sincrono per l'adapter Echo.

Cosa ho fatto?

È stata appena implementata la funzionalità di risoluzione dei metadati per l'adattatore echo.

Passaggi successivi

Nel passaggio successivo si implementa il gestore in uscita sincrono per l'adapter Echo. Si implementa quindi il gestore in ingresso sincrono e quindi si compila e distribuisce l'adapter Echo.

Vedere anche

Passaggio 5: Implementare il gestore per la ricerca di metadati per Echo Adapter
Passaggio 7: Implementare il gestore in uscita sincrono per Echo Adapter
Esercitazione 1: Sviluppare Echo Adapter