Partager via


Étape 6 : Implémenter le gestionnaire de résolution des métadonnées pour l’adaptateur Echo

Étape 6 sur 9

Durée d’exécution : 45 minutes

Dans cette étape, vous implémentez l’interface pour résoudre l’opération Microsoft.ServiceModel.Channels.Common.IMetadataResolverHandler et les métadonnées de type pour l’adaptateur d’écho. Quelle que soit la capacité de votre adaptateur, vous devez implémenter cette interface. L’Assistant Développement d’adaptateur génère automatiquement la classe dérivée appelée EchoAdapterMetadataResolverHandler pour vous.

Dans la section suivante, vous mettez à jour la classe EchoAdapterMetadataResolverHandler pour mieux comprendre comment implémenter cette interface. Lorsque vous effectuez cette étape, vous disposez d’un gestionnaire de résolution de métadonnées opérationnel pour l’adaptateur d’écho.

Prérequis

Avant de commencer cette étape, vous devez avoir effectué l’étape 5 : Implémenter le gestionnaire de recherche de métadonnées pour l’adaptateur Echo. Vous devez également comprendre les classes d’opération et de type suivantes :

  • 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

The IMetadataResolverHandler Interface

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);  
  }  

Le tableau suivant décrit ce que fait chaque méthode :

Nom de la méthode Description
IsOperationMetadataValid Retourne une valeur true si les métadonnées de type n’ont pas changé depuis la date et l’heure spécifiées
IsTypeMetadataValid Retourne une valeur booléenne qui indique si les métadonnées de type spécifiées sont valides.
ResolveOperationMetadata Résout un ID d’opération en correspondant Microsoft.ServiceModel.Channels.Common.OperationMetadata
ResolveTypeMetadata Résout un typeId de métadonnées fourni en un correspondant Microsoft.ServiceModel.Channels.Common.TypeMetadata.

Pour implémenter la méthode IsOperationMetadataValid

  1. Dans Explorateur de solutions, double-cliquez sur le fichier EchoAdapterMetadataResolverHandler.cs.

  2. Dans l’éditeur Visual Studio, cliquez avec le bouton droit n’importe où dans l’éditeur, dans le menu contextuel, pointez sur Plan, puis cliquez sur Arrêter le plan.

  3. Dans l’éditeur Visual Studio, recherchez la méthode IsOperationMetadataValid , à l’intérieur de cette méthode, remplacez l’existant par l’instruction unique suivante pour indiquer que chaque métadonnées d’opération spécifiée est valide.

    return true;  
    

Pour implémenter la méthode IsTypeMetadataValid

  • Dans l’éditeur Visual Studio, recherchez la méthode IsTypeMetadataValid , dans cette méthode, remplacez l’existant par l’instruction unique suivante pour indiquer que chaque métadonnées de type spécifié est valide.

    return true;  
    

Pour implémenter la méthode ResolveOperationMetadata

  1. Dans l’éditeur Visual Studio, recherchez la méthode ResolveOperationMetadata , dans cette méthode, remplacez l’existant par le suivant pour résoudre l’opération OnReceiveEcho, void OnReceiveEcho(Chemin d’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. Continuez à ajouter ce qui suit pour résoudre l’opération 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. Continuez à ajouter la logique suivante pour résoudre l’opération Echo/EchoStrings, string[] 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. Continuez à ajouter la logique suivante pour résoudre l’opération 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. Continuez à ajouter ce qui suit pour gérer la casse par défaut.

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

Pour implémenter la méthode ResolveTypeMetadata

  • Dans l’éditeur Visual Studio, recherchez la méthode ResolveTypeMetadata , à l’intérieur de cette méthode, remplacez l’existant par le suivant pour renvoyer un Microsoft.ServiceModel.Channels.Common.TypeMetadata objet.

    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);  
    }  
    
    

Pour définir la classe de métadonnées de type de message d’accueil personnalisé

  1. Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet Adaptateur Echo, pointez sur Ajouter, puis cliquez sur Nouvel élément.

  2. Dans la boîte de dialogue Ajouter un nouvel élément , sous Modèles, cliquez sur Classe.

  3. Dans la zone de texte Nom , tapez CustomGreetingTypeMetadata.

  4. Cliquez sur Add.

  5. Dans l’éditeur Visual Studio, remplacez le code existant par ce qui suit :

    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. Dans Visual Studio, dans le menu Fichier , cliquez sur Enregistrer tout.

Pour créer la définition de schéma XML de salutation personnalisée

  1. Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet Adaptateur Echo, pointez sur Ajouter, puis cliquez sur Nouvel élément.

  2. Dans la boîte de dialogue Ajouter un nouvel élément , sous Modèles, cliquez sur Schéma XML.

  3. Dans la zone de texte Nom , tapez CustomGreeting.

  4. Cliquez sur Ajouter.

  5. Dans Explorateur de solutions, cliquez avec le bouton droit sur le fichier CustomGreeting.xsd et choisissez Afficher le code.

  6. Dans l’éditeur Visual Studio, commencez par remplacer le code existant par le code suivant qui commence la définition du schéma 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>  
    

    avec le code suivant qui commence la définition du schéma 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. Ajoutez les éléments suivants pour définir l’élément CustomGreeting :

    <xsd:element name="greeting" type="CustomGreeting" />  
    
  8. Ajoutez maintenant la définition du type complexe 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. Poursuivez la définition de schéma CustomGreeting en ajoutant le type complexe 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. Terminez la définition du schéma CustomGreeting en ajoutant le type simple PostalCode et la balise fermante pour le schéma :

      <xsd:simpleType name="PostalCode">  
        <xsd:restriction base="xsd:positiveInteger">  
          <xsd:pattern value="\d{5}" />  
        </xsd:restriction>  
      </xsd:simpleType>  
    </xsd:schema>  
    
  11. Maintenant, mettez à jour l’action de génération pour ce fichier afin qu’il soit traité comme une ressource incorporée. Pour ce faire, dans le volet de la solution Visual Studio, cliquez avec le bouton droit sur le fichier et choisissez Propriétés. Modifiez l’action de génération de None en Ressource incorporée.

  12. Dans Visual Studio, dans le menu Fichier , cliquez sur Enregistrer tout.

Notes

Vous avez enregistré votre travail. Vous pouvez fermer Visual Studio en toute sécurité à ce stade ou passer à l’étape suivante, Étape 7 : Implémenter le gestionnaire sortant synchrone pour l’adaptateur Echo.

Qu’est-ce que je viens de faire ?

Vous venez d’implémenter la fonctionnalité de résolution des métadonnées pour l’adaptateur d’écho.

Étapes suivantes

À l’étape suivante, vous allez implémenter le gestionnaire sortant synchrone pour l’adaptateur Echo. Vous implémentez ensuite le gestionnaire entrant synchrone, puis générez et déployez l’adaptateur Echo.

Voir aussi

Étape 5 : Implémenter le gestionnaire de recherche de métadonnées pour l’adaptateur Echo
Étape 7 : Implémenter le gestionnaire de trafic sortant synchrone pour l’adaptateur Echo
Didacticiel 1 : Développer l’adaptateur Echo