完了までの時間: 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 メソッドを実装するには
ソリューション エクスプローラーで、 EchoAdapterMetadataResolverHandler.cs ファイルをダブルクリックします。
Visual Studio エディターで、エディター内の任意の場所を右クリックし、コンテキスト メニューで [ アウトライン] をポイントし、[ アウトラインの停止] をクリックします。
Visual Studio エディターで 、IsOperationMetadataValid メソッドを見つけます。このメソッド内で、指定されたすべての操作メタデータが有効であることを示すために、既存のステートメントを次の 1 つのステートメントに置き換えます。
return true;
IsTypeMetadataValid メソッドを実装するには
Visual Studio エディターで 、IsTypeMetadataValid メソッドを見つけます。このメソッド内で、既存のものを次の単一のステートメントに置き換えて、指定されたすべての型メタデータが有効であることを示します。
return true;
ResolveOperationMetadata メソッドを実装するには
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;
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;
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;
次のロジックを追加し続けて、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;
既定のケースを処理するために、以下の手順を引き続き行ってください。
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); }
カスタム あいさつ文型メタデータ クラスを定義するには
ソリューション エクスプローラーで、 Echo Adapter プロジェクトを右クリックし、[ 追加] をポイントして、[ 新しい項目] をクリックします。
[ 新しい項目の追加 ] ダイアログ ボックスの [ テンプレート] で、[ クラス] をクリックします。
[ 名前 ] テキスト ボックスに「 CustomGreetingTypeMetadata」と入力します。
追加をクリックします。
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; } } } }
Visual Studio の [ ファイル ] メニューの [ すべて保存] をクリックします。
カスタム あいさつ XML スキーマ定義を作成するには
ソリューション エクスプローラーで、 Echo Adapter プロジェクトを右クリックし、[ 追加] をポイントして、[ 新しい項目] をクリックします。
[ 新しい項目の追加 ] ダイアログ ボックスの [ テンプレート] で、[ XML スキーマ] をクリックします。
[ 名前 ] テキスト ボックスに「 CustomGreeting」と入力します。
追加をクリックします。
ソリューション エクスプローラーで、 CustomGreeting.xsd ファイルを 右クリックし、[ コードの表示] を選択します。
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">
CustomGreeting 要素を定義するには、次を追加します。
<xsd:element name="greeting" type="CustomGreeting" />
次に、CustomGreeting 複合型の定義を追加します。
<xsd:complexType name="CustomGreeting"> <xsd:sequence> <xsd:element name="address" type="UsAddress" /> <xsd:element name="greetingText" type="xsd:string" /> </xsd:sequence> </xsd:complexType>
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>
PostalCode 単純型とスキーマの終了タグを追加して、CustomGreeting スキーマの定義を完了します。
<xsd:simpleType name="PostalCode"> <xsd:restriction base="xsd:positiveInteger"> <xsd:pattern value="\d{5}" /> </xsd:restriction> </xsd:simpleType> </xsd:schema>
次に、埋め込みリソースとして扱われるように、このファイルのビルド アクションを更新します。 これを行うには、Visual Studio ソリューション ウィンドウでファイルを右クリックし、[ プロパティ] を選択します。 ビルド アクションを [なし] から [埋め込みリソース] に変更します。
Visual Studio の [ ファイル ] メニューの [ すべて保存] をクリックします。
注
作業を保存しました。 この時点で Visual Studio を安全に閉じるか、次の手順「 手順 7: エコー アダプターの同期送信ハンドラーを実装する」に進むことができます。
私は何をしましたか?
エコー アダプターのメタデータ解決機能を実装しました。
次のステップ
次の手順では、エコー アダプターの同期送信ハンドラーを実装します。 次に、同期受信ハンドラーを実装し、エコー アダプターをビルドして展開します。
こちらもご覧ください
手順 5: エコー アダプターのメタデータ検索ハンドラーを実装する
手順 7: エコー アダプターの同期送信ハンドラーを実装する
チュートリアル 1: エコー アダプターを開発する