次の方法で共有


手順 6: エコー アダプターのメタデータ解決ハンドラーを実装する

手順 6/9

完了までの時間: 45 分

この手順では、 Microsoft.ServiceModel.Channels.Common.IMetadataResolverHandler インターフェイスを実装して、エコー アダプターの操作と型のメタデータを解決します。 アダプターの機能に関係なく、このインターフェイスを実装する必要があります。 アダプター開発ウィザードでは、EchoAdapterMetadataResolverHandler という名前の派生クラスが自動的に生成されます。

次のセクションでは、EchoAdapterMetadataResolverHandler クラスを更新して、このインターフェイスを実装する方法について理解を深めます。 この手順を完了すると、エコー アダプターのメタデータ解決ハンドラーが動作します。

[前提条件]

この手順を開始する前に、「 手順 5: Echo アダプターのメタデータ検索ハンドラーを実装する」を正常に完了している必要があります。 また、次の操作クラスと型クラスについても理解する必要があります。

  • 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

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

次の表では、各メソッドの動作について説明します。

メソッド名 説明
IsOperationMetadataValid 指定した日付と時刻以降に型メタデータが変更されていない場合は true を返します。
IsTypeMetadataValid 指定した型メタデータが有効かどうかを示すブール値を返します。
ResolveOperationMetadata 操作 ID を対応する操作 ID に解決します。 Microsoft.ServiceModel.Channels.Common.OperationMetadata
ResolveTypeMetadata 指定されたメタデータ typeId を対応する Microsoft.ServiceModel.Channels.Common.TypeMetadataに解決します。

IsOperationMetadataValid メソッドを実装するには

  1. ソリューション エクスプローラーで、 EchoAdapterMetadataResolverHandler.cs ファイルをダブルクリックします。

  2. Visual Studio エディターで、エディター内の任意の場所を右クリックし、コンテキスト メニューで [ アウトライン] をポイントし、[ アウトラインの停止] をクリックします。

  3. Visual Studio エディターで 、IsOperationMetadataValid メソッドを見つけます。このメソッド内で、指定されたすべての操作メタデータが有効であることを示すために、既存のステートメントを次の 1 つのステートメントに置き換えます。

    return true;  
    

IsTypeMetadataValid メソッドを実装するには

  • Visual Studio エディターで 、IsTypeMetadataValid メソッドを見つけます。このメソッド内で、既存のものを次の単一のステートメントに置き換えて、指定されたすべての型メタデータが有効であることを示します。

    return true;  
    

ResolveOperationMetadata メソッドを実装するには

  1. Visual Studio エディターで ResolveOperationMetadata メソッドを見つけます。このメソッド内で既存のものを次のメソッドに置き換えて、OnReceiveEcho 操作 void OnReceiveEcho(Uri path, 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. 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. 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. 次のロジックを追加し続けて、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. 既定のケースを処理するために、以下の手順を引き続き行ってください。

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

ResolveTypeMetadata メソッドを実装するには

  • Visual Studio エディターで ResolveTypeMetadata メソッドを見つけます。このメソッド内で、既存のものを次に置き換えて、 Microsoft.ServiceModel.Channels.Common.TypeMetadata オブジェクトを返します。

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

カスタム あいさつ文型メタデータ クラスを定義するには

  1. ソリューション エクスプローラーで、 Echo Adapter プロジェクトを右クリックし、[ 追加] をポイントして、[ 新しい項目] をクリックします。

  2. [ 新しい項目の追加 ] ダイアログ ボックスの [ テンプレート] で、[ クラス] をクリックします。

  3. [ 名前 ] テキスト ボックスに「 CustomGreetingTypeMetadata」と入力します。

  4. 追加をクリックします。

  5. Visual Studio エディターで、既存のコードを次のコードに置き換えます。

    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. Visual Studio の [ ファイル ] メニューの [ すべて保存] をクリックします。

カスタム あいさつ XML スキーマ定義を作成するには

  1. ソリューション エクスプローラーで、 Echo Adapter プロジェクトを右クリックし、[ 追加] をポイントして、[ 新しい項目] をクリックします。

  2. [ 新しい項目の追加 ] ダイアログ ボックスの [ テンプレート] で、[ XML スキーマ] をクリックします。

  3. [ 名前 ] テキスト ボックスに「 CustomGreeting」と入力します。

  4. 追加をクリックします。

  5. ソリューション エクスプローラーで、 CustomGreeting.xsd ファイルを 右クリックし、[ コードの表示] を選択します。

  6. Visual Studio エディターで、まず、既存のコードを 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>  
    

    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. CustomGreeting 要素を定義するには、次を追加します。

    <xsd:element name="greeting" type="CustomGreeting" />  
    
  8. 次に、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. UsAddress 複合型を追加して、CustomGreeting スキーマ定義を続行します。

    <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. PostalCode 単純型とスキーマの終了タグを追加して、CustomGreeting スキーマの定義を完了します。

      <xsd:simpleType name="PostalCode">  
        <xsd:restriction base="xsd:positiveInteger">  
          <xsd:pattern value="\d{5}" />  
        </xsd:restriction>  
      </xsd:simpleType>  
    </xsd:schema>  
    
  11. 次に、埋め込みリソースとして扱われるように、このファイルのビルド アクションを更新します。 これを行うには、Visual Studio ソリューション ウィンドウでファイルを右クリックし、[ プロパティ] を選択します。 ビルド アクションを [なし] から [埋め込みリソース] に変更します

  12. Visual Studio の [ ファイル ] メニューの [ すべて保存] をクリックします。

作業を保存しました。 この時点で Visual Studio を安全に閉じるか、次の手順「 手順 7: エコー アダプターの同期送信ハンドラーを実装する」に進むことができます。

私は何をしましたか?

エコー アダプターのメタデータ解決機能を実装しました。

次のステップ

次の手順では、エコー アダプターの同期送信ハンドラーを実装します。 次に、同期受信ハンドラーを実装し、エコー アダプターをビルドして展開します。

こちらもご覧ください

手順 5: エコー アダプターのメタデータ検索ハンドラーを実装する
手順 7: エコー アダプターの同期送信ハンドラーを実装する
チュートリアル 1: エコー アダプターを開発する