Schritt 6: Implementieren des Handlers zum Löschen von Metadaten für den Echo-Adapter
Dauer: 45 Minuten
In diesem Schritt implementieren Sie die Schnittstelle, um den Microsoft.ServiceModel.Channels.Common.IMetadataResolverHandler
Vorgang aufzulösen und Metadaten für den Echoadapter einzugeben. Unabhängig von der Funktion Ihres Adapters müssen Sie diese Schnittstelle implementieren. Der Adapterentwicklungs-Assistent generiert automatisch die abgeleitete Klasse mit dem Namen EchoAdapterMetadataResolverHandler für Sie.
Im folgenden Abschnitt aktualisieren Sie die EchoAdapterMetadataResolverHandler-Klasse, um ein besseres Verständnis für die Implementierung dieser Schnittstelle zu erhalten. Wenn Sie diesen Schritt ausführen, verfügen Sie über einen funktionierenden Metadatenlösehandler für den Echoadapter.
Voraussetzungen
Bevor Sie mit diesem Schritt beginnen, müssen Sie Schritt 5: Implementieren des Metadatensuchhandlers für den Echoadapter erfolgreich abgeschlossen haben. Sie müssen auch die folgenden Vorgangs- und Typklassen kennen:
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
Die IMetadataResolverHandler-Schnittstelle
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);
}
In der folgenden Tabelle wird die Funktionsweise der einzelnen Methoden beschrieben:
Methodenname | Beschreibung |
---|---|
IsOperationMetadataValid | Gibt true zurück, wenn sich die Typmetadaten seit dem angegebenen Datum und der angegebenen Uhrzeit nicht geändert haben. |
IsTypeMetadataValid | Gibt einen booleschen Wert zurück, der angibt, ob die angegebenen Typmetadaten gültig sind. |
ResolveOperationMetadata | Löst eine Vorgangs-ID in die entsprechende auf. Microsoft.ServiceModel.Channels.Common.OperationMetadata |
ResolveTypeMetadata | Löst eine angegebene Metadatentyp-ID in eine entsprechende Microsoft.ServiceModel.Channels.Common.TypeMetadata auf. |
So implementieren Sie die IsOperationMetadataValid-Methode
Doppelklicken Sie in Projektmappen-Explorer auf die Datei EchoAdapterMetadataResolverHandler.cs.
Klicken Sie im Visual Studio-Editor mit der rechten Maustaste auf eine beliebige Stelle im Editor, zeigen Sie im Kontextmenü auf Gliederung, und klicken Sie dann auf Gliederung beenden.
Suchen Sie im Visual Studio-Editor nach der IsOperationMetadataValid-Methode . Ersetzen Sie in dieser Methode die vorhandene durch die folgende einzelne Anweisung, um anzugeben, dass alle angegebenen Vorgangsmetadaten gültig sind.
return true;
So implementieren Sie die IsTypeMetadataValid-Methode
Suchen Sie im Visual Studio-Editor nach der IsTypeMetadataValid-Methode . Ersetzen Sie in dieser Methode die vorhandene durch die folgende einzelne Anweisung, um anzugeben, dass alle angegebenen Typmetadaten gültig sind.
return true;
So implementieren Sie die ResolveOperationMetadata-Methode
Suchen Sie im Visual Studio-Editor nach der ResolveOperationMetadata-Methode . Ersetzen Sie in dieser Methode die vorhandene durch den folgenden, um den OnReceiveEcho-Vorgang void OnReceiveEcho(Uri path, long fileLength) aufzulösen.
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;
Fügen Sie folgendes hinzu, um den Echo/EchoStrings-Vorgang string[] EchoStrings(Zeichenfolgendaten) aufzulösen.
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;
Fahren Sie mit dem Hinzufügen der folgenden Logik fort, um den Echo/EchoStrings-Vorgang string[] EchoStrings(Zeichenfolgendaten) aufzulösen.
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;
Fahren Sie mit dem Hinzufügen der folgenden Logik fort, um den Vorgang CustomGreeting EchoCustomGreetingFromFile(Uri greetingInstancePath) aufzulösen.
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;
Fügen Sie mit dem Folgenden fort, um die Standard-Groß-/Kleinschreibung zu behandeln.
default: throw new AdapterException("Cannot resolve metadata for operation identifier " + operationId); }
So implementieren Sie die ResolveTypeMetadata-Methode
Suchen Sie im Visual Studio-Editor nach der ResolveTypeMetadata-Methode . Ersetzen Sie in dieser Methode die vorhandene durch Folgendes, um ein
Microsoft.ServiceModel.Channels.Common.TypeMetadata
-Objekt zurückzugeben.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); }
So definieren Sie die Metadatenklasse des benutzerdefinierten Begrüßungstyps
Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Echoadapterprojekt, zeigen Sie auf Hinzufügen, und klicken Sie dann auf Neues Element.
Klicken Sie im Dialogfeld Neues Element hinzufügen unter Vorlagen auf Klasse.
Geben Sie im Textfeld Name den Namen CustomGreetingTypeMetadata ein.
Klicken Sie auf Hinzufügen.
Ersetzen Sie im Visual Studio-Editor den vorhandenen Code durch Folgendes:
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; } } } }
Klicken Sie in Visual Studio im Menü Datei auf Alle speichern.
So erstellen Sie die benutzerdefinierte XML-Schemadefinition für die Begrüßung
Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Echoadapterprojekt, zeigen Sie auf Hinzufügen, und klicken Sie dann auf Neues Element.
Klicken Sie im Dialogfeld Neues Element hinzufügen unter Vorlagen auf XML-Schema.
Geben Sie im Textfeld Name den Namen CustomGreeting ein.
Klicken Sie auf Hinzufügen.
Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf die Datei CustomGreeting.xsd, und wählen Sie Code anzeigen aus.
Ersetzen Sie im Visual Studio-Editor zunächst den vorhandenen Code durch den folgenden Code, der die Definition des CustomGreeting-Schemas beginnt:
<?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>
mit dem folgenden Code, der die Definition des CustomGreeting-Schemas beginnt:
<?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">
Fügen Sie Folgendes hinzu, um das CustomGreeting-Element zu definieren:
<xsd:element name="greeting" type="CustomGreeting" />
Fügen Sie nun die Definition des komplexen CustomGreeting-Typs hinzu:
<xsd:complexType name="CustomGreeting"> <xsd:sequence> <xsd:element name="address" type="UsAddress" /> <xsd:element name="greetingText" type="xsd:string" /> </xsd:sequence> </xsd:complexType>
Fahren Sie mit der CustomGreeting-Schemadefinition fort, indem Sie den komplexen UsAddress-Typ hinzufügen:
<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>
Vervollständigen Sie die Definition des CustomGreeting-Schemas, indem Sie den einfachen PostalCode-Typ und das schließende Tag für das Schema hinzufügen:
<xsd:simpleType name="PostalCode"> <xsd:restriction base="xsd:positiveInteger"> <xsd:pattern value="\d{5}" /> </xsd:restriction> </xsd:simpleType> </xsd:schema>
Aktualisieren Sie nun die Buildaktion für diese Datei, sodass sie als eingebettete Ressource behandelt wird. Klicken Sie hierzu im Visual Studio-Projektmappenbereich mit der rechten Maustaste auf die Datei, und wählen Sie Eigenschaften aus. Ändern Sie die Buildaktion von Keine in eingebettete Ressource.
Klicken Sie in Visual Studio im Menü Datei auf Alle speichern.
Hinweis
Sie haben Ihre Arbeit gespeichert. Sie können Visual Studio zu diesem Zeitpunkt sicher schließen oder mit dem nächsten Schritt fortfahren, Schritt 7: Implementieren des synchronen ausgehenden Handlers für den Echoadapter.
Was habe ich gerade getan?
Sie haben gerade die Funktion zum Auflösen von Metadaten für den Echoadapter implementiert.
Nächste Schritte
Im nächsten Schritt implementieren Sie den synchronen ausgehenden Handler für den Echoadapter. Anschließend implementieren Sie den synchronen eingehenden Handler und erstellen und stellen dann den Echoadapter bereit.
Weitere Informationen
Schritt 5: Implementieren des Handlers zum Suchen nach Metadaten für den Echo-Adapter
Schritt 7: Implementieren des synchronen Ausgangshandlers für den Echo-Adapter
Tutorial 1: Entwickeln des Echo-Adapters