Datenvertrag-ErsatzzeichenData Contract Surrogates

Der Datenvertrag Ersatzzeichen ist eine erweiterte Funktion, die auf dem datenvertragsmodell basiert.The data contract surrogate is an advanced feature built upon the Data Contract model. Diese Funktion wurde zur Verwendung für die Typanpassung und -ersetzung entwickelt, wenn Benutzer Änderungen daran vornehmen möchten, wie ein Typ serialisiert, deserialisiert oder in Metadaten projiziert wird.This feature is designed to be used for type customization and substitution in situations where users want to change how a type is serialized, deserialized or projected into metadata. Einige Szenarien, in denen ein Ersatzzeichen verwendet werden kann, sind die fehlende Spezifizierung eines Datenvertrags für den Typ, die fehlende Markierung von Feldern und Eigenschaften mit dem DataMemberAttribute-Attribut oder wenn Benutzer die dynamische Erstellung von Schemavarianten wünschen.Some scenarios where a surrogate may be used is when a data contract has not been specified for the type, fields and properties are not marked with the DataMemberAttribute attribute or users wish to dynamically create schema variations.

Serialisierung und Deserialisierung werden mit dem Datenvertrag-Ersatzzeichen erreicht, wenn DataContractSerializer zum Konvertieren aus .NET Framework in ein geeignetes Format, wie z. B. XML, verwendet wird.Serialization and deserialization are accomplished with the data contract surrogate when using DataContractSerializer to convert from .NET Framework to a suitable format, such as XML. Das Datenvertrag-Ersatzzeichen kann auch verwendet werden, um die für Typen exportierten Metadaten zu ändern, wenn Metadatendarstellungen, wie z. B. XML Schema Documents (XSD), erstellt werden.Data contract surrogate can also be used to modify the metadata exported for types, when producing metadata representations such as XML Schema Documents (XSD). Beim Importieren wird der Code aus den Metadaten erstellt, und das Ersatzzeichen kann in diesem Fall verwendet werden, um auch den generierten Code anzupassen.Upon import, code is created from metadata and the surrogate can be used in this case to customize the generated code as well.

So funktioniert das ErsatzzeichenHow the Surrogate Works

Ein Ersatzzeichen funktioniert, indem es einen Typ (den "ursprünglichen" Typ) einem anderen Typ (dem "ersetzten" Typ) zuordnet.A surrogate works by mapping one type (the "original" type) to another type (the "surrogated" type). Im folgenden Beispiel werden der ursprüngliche Typ Inventory und ein neuer Ersatzzeichen-InventorySurrogated-Typ veranschaulicht.The following example shows the original type Inventory and a new surrogate InventorySurrogated type. Der Typ Inventory ist nicht serialisierbar, aber der Typ InventorySurrogated ist serialisierbar:The Inventory type is not serializable but the InventorySurrogated type is:

public class Inventory
{
    public int pencils;
    public int pens;
    public int paper;
}

Weil für diese Klasse kein Datenvertrag definiert wurde, soll die Klasse in eine Ersatzzeichenklasse mit einem Datenvertrag konvertiert werden.Because a data contract has not been defined for this class, convert the class to a surrogate class with a data contract. Die ersetzte Klasse wird im folgenden Beispiel gezeigt:The surrogated class is shown in the following example:

[DataContract(Name = "Inventory")]
public class InventorySurrogated
{
    [DataMember]
    public int numpencils;
    [DataMember]
    public int numpaper;
    [DataMember]
    private int numpens;

    public int pens
    {
        get { return numpens; }
        set { numpens = value; }
    }
}

Implementieren des IDataContractSurrogateImplementing the IDataContractSurrogate

Zur Verwendung des Datenvertrag-Ersatzzeichens implementieren Sie die IDataContractSurrogate-Schnittstelle.To use the data contract surrogate, implement the IDataContractSurrogate interface.

Es folgt eine Übersicht über jede Methode von IDataContractSurrogate mit einer möglichen Implementierung.The following is an overview of each method of IDataContractSurrogate with a possible implementation.

GetDataContractTypeGetDataContractType

Die GetDataContractType-Methode ordnet einen Typ einem anderen zu.The GetDataContractType method maps one type to another. Diese Methode ist für Serialisierung, Deserialisierung, Import und Export erforderlich.This method is required for serialization, deserialization, import, and export.

Die erste Aufgabe definiert, welche Typen anderen Typen zugeordnet werden.The first task is defining what types will be mapped to other types. Zum Beispiel:For example:

public Type GetDataContractType(Type type)
{
    Console.WriteLine("GetDataContractType");
    if (typeof(Inventory).IsAssignableFrom(type))
    {
        return typeof(InventorySurrogated);
    }
    return type;
}
  • Bei der Serialisierung wird die durch diese Methode zurückgegebene Zuordnung verwendet, um die ursprüngliche Instanz in eine ersetzte Instanz zu transformieren, indem die GetObjectToSerialize-Methode aufgerufen wird.On serialization, the mapping returned by this method is subsequently used to transform the original instance to a surrogated instance by calling the GetObjectToSerialize method.

  • Bei der Deserialisierung wird die durch diese Methode zurückgegebene Zuordnung durch das Serialisierungsprogramm verwendet, um die Deserialisierung in eine Instanz des Ersatzzeichentyps durchzuführen.On deserialization, the mapping returned by this method is used by the serializer to deserialize into an instance of the surrogate type. Es ruft anschließend GetDeserializedObject auf, um die ersetzte Instanz in eine Instanz des ursprünglichen Typs zu transformieren.It subsequently calls GetDeserializedObject to transform the surrogated instance into an instance of the original type.

  • Beim Export wird der durch diese Methode zurückgegebene Ersatzzeichentyp reflektiert, um den Datenvertrag zu erhalten, der zur Generierung von Metadaten verwendet werden soll.On export, the surrogate type returned by this method is reflected to get the data contract to use for generating metadata.

  • Beim Import wird der Ausgangstyp in einen Ersatzzeichentyp geändert und reflektiert, um den Datenvertrag, der für Zwecke wie den Support-Verweis verwendet werden soll, zu erhalten.On import, the initial type is changed to a surrogate type that is reflected to get the data contract to use for purposes like referencing support.

Der Type-Parameter ist der Typ des Objekts, das serialisiert, deserialisiert, importiert oder exportiert wird.The Type parameter is the type of the object that is being serialized, deserialized, imported, or exported. Die GetDataContractType-Methode muss den Eingabetyp zurückgeben, wenn das Ersatzzeichen den Typ nicht behandelt.The GetDataContractType method must return the input type if the surrogate does not handle the type. Ansonsten wird der entsprechende Ersatzzeichentyp zurückgegeben.Otherwise, return the appropriate surrogated type. Wenn mehrere Ersatzzeichentypen vorhanden sind, können zahlreiche Zuordnungen in dieser Methode definiert werden.If several surrogate types exist, numerous mappings can be defined in this method.

Die GetDataContractType-Methode wird nicht für integrierte Datenvertragsprimitiven, z. B. Int32 oder String, aufgerufen.The GetDataContractType method is not called for built-in data contract primitives, such as Int32 or String. Für andere Typen, wie z. B. Arrays, benutzerdefinierte Typen und andere Datenstrukturen, wird diese Methode für jeden Typ aufgerufen.For other types, such as arrays, user-defined types, and other data structures, this method will be called for each type.

Beim vorherigen Beispiel überprüft die Methode, ob der type-Parameter und Inventory vergleichbar sind.In the previous example, the method checks if the type parameter and Inventory are comparable. Wenn das der Fall ist, führt die Methode eine Zuordnung zu InventorySurrogated durch.If so, the method maps it to InventorySurrogated. Bei jedem Aufrufen einer Serialisierung, einer Deserialisierung, eines Importschemas oder eines Exportschemas wird diese Funktion zuerst aufgerufen, um die Zuordnung zwischen den Typen zu ermitteln.Whenever a serialization, deserialization, import schema, or export schema is called, this function is called first to determine the mapping between types.

GetObjectToSerialize-MethodeGetObjectToSerialize Method

Die GetObjectToSerialize-Methode konvertiert die Instanz des ursprünglichen Typs in die Instanz des Ersatzzeichentyps.The GetObjectToSerialize method converts the original type instance to the surrogated type instance. Die Methode ist für die Serialisierung erforderlich.The method is required for serialization.

Der nächste Schritt besteht darin zu definieren, wie die physikalischen Daten von der ursprünglichen Instanz zur Ersatzzeicheninstanz erfolgen soll, indem die GetObjectToSerialize-Methode implementiert wird.The next step is to define the way the physical data will be mapped from the original instance to the surrogate by implementing the GetObjectToSerialize method. Zum Beispiel:For example:

public object GetObjectToSerialize(object obj, Type targetType)
{
    Console.WriteLine("GetObjectToSerialize");
    if (obj is Inventory)
    {
        InventorySurrogated isur = new InventorySurrogated();
        isur.numpaper = ((Inventory)obj).paper;
        isur.numpencils = ((Inventory)obj).pencils;
        isur.pens = ((Inventory)obj).pens;
        return isur;
    }
    return obj;
}

Die GetObjectToSerialize-Methode wird aufgerufen, wenn ein Objekt serialisiert wird.The GetObjectToSerialize method is called when an object is serialized. Diese Methode überträgt Daten vom ursprünglichen Typ auf die Felder des Ersatzzeichentyps.This method transfers data from the original type to the fields of the surrogated type. Die Felder können den Ersatzzeichenfeldern direkt zugeordnet werden, oder in dem Ersatzzeichen können Bearbeitungen der ursprünglichen Daten gespeichert werden.Fields can be directly mapped to surrogate fields, or manipulations of the original data may be stored in the surrogate. Zu den Verwendungsmöglichkeiten zählen: direktes Zuordnen der Felder, Durchführen von Vorgängen an den Daten, die in den Ersatzzeichenfeldern gespeichert werden sollen, oder Speichern der XML des ursprünglichen Typs in dem Ersatzzeichenfeld.Some possible uses include: directly mapping the fields, performing operations on the data to be stored in the surrogated fields, or storing the XML of the original type in the surrogated field.

Der targetType-Parameter verweist auf den deklarierten Typ des Members.The targetType parameter refers to the declared type of the member. Dieser Parameter ist der Ersatzzeichentyp, der durch die GetDataContractType-Methode zurückgegeben wird.This parameter is the surrogated type returned by the GetDataContractType method. Vom Serialisierungsprogramm wird nicht erzwungen, dass das zurückgegebene Objekt diesem Typ zugeordnet werden kann.The serializer does not enforce that the object returned is assignable to this type. Die obj -Parameter ist das Objekt zu serialisieren, und wird in sein Ersatzzeichen konvertiert werden, falls erforderlich.The obj parameter is the object to serialize, and will be converted to its surrogate if necessary. Diese Methode muss den Eingabeobjekttyp zurückgeben, wenn das Ersatzzeichen das Objekt nicht behandelt.This method must return the input object if the surrogated does not handle the object. Andernfalls wird das neue Ersatzzeichenobjekt zurückgegeben.Otherwise, the new surrogate object will be returned. Das Ersatzzeichen wird nicht aufgerufen, wenn das Objekt NULL ist.The surrogate is not called if the object is null. Innerhalb dieser Methode werden möglicherweise zahlreiche Ersatzzeichenzuordnungen für verschiedene Instanzen definiert.Numerous surrogate mappings for different instances may be defined within this method.

Wenn Sie ein DataContractSerializer erstellen, können Sie es anweisen, Objektverweise beizubehalten.When creating a DataContractSerializer, you can instruct it to preserve object references. (Weitere Informationen finden Sie unter Serialisierung und Deserialisierung.) Dazu wird der preserveObjectReferences-Parameter in seinem Konstruktor auf true festlegt.(For more information, see Serialization and Deserialization.) This is done by setting the preserveObjectReferences parameter in its constructor to true. In diesem Fall wird das Ersatzzeichen für ein Objekt nur ein einziges Mal aufgerufen, weil alle nachfolgenden Serialisierungen lediglich den Verweis in den Stream schreiben.In that case, the surrogate is called only once for an object since all subsequent serializations just write the reference into the stream. Wenn preserveObjectReferences auf false festgelegt wird, dann wird das Ersatzzeichen jedes Mal aufgerufen, wenn eine Instanz gefunden wird.If preserveObjectReferences is set to false, then the surrogate is called every time an instance is encountered.

Wenn der Typ der serialisierten Instanz vom deklarierten Typ abweicht, werden Typinformationen in den Stream geschrieben, z. B. xsi:type, um die Deserialisierung der Instanz am anderen Ende zu ermöglichen.If the type of the instance serialized differs from the declared type, type information is written into the stream, for example, xsi:type to allow the instance to be deserialized at the other end. Dieser Prozess tritt unabhängig davon auf, ob das Objekt ersetzt wurde oder nicht.This process occurs whether the object is surrogated or not.

Das obige Beispiel konvertiert die Daten der Inventory-Instanz zu denen von InventorySurrogated.The example above converts the data of the Inventory instance to that of InventorySurrogated. Es überprüft den Objekttyp und führt die erforderlichen Bearbeitungen durch, um die Konvertierung in den Ersatzzeichentyp zu bewirken.It checks the type of the object and performs the necessary manipulations to convert to the surrogated type. In diesem Fall werden die Felder der Inventory-Klasse direkt über die Felder der InventorySurrogated-Klasse kopiert.In this case, the fields of the Inventory class are directly copied over to the InventorySurrogated class fields.

GetDeserializedObject-MethodeGetDeserializedObject Method

Die GetDeserializedObject-Methode konvertiert die Ersatzzeichentypinstanz in die Instanz des ursprünglichen Typs.The GetDeserializedObject method converts the surrogated type instance to the original type instance. Sie ist für die Deserialisierung erforderlich.It is required for deserialization.

Die nächste Aufgabe besteht darin zu definieren, wie die physikalischen Daten von der Ersatzzeicheninstanz zur ursprünglichen Instanz zugeordnet werden sollen.The next task is to define the way the physical data will be mapped from the surrogate instance to the original. Zum Beispiel:For example:

public object GetDeserializedObject(object obj, Type targetType)
{
    Console.WriteLine("GetDeserializedObject");
    if (obj is InventorySurrogated)
    {
        Inventory invent = new Inventory();
        invent.pens = ((InventorySurrogated)obj).pens;
        invent.pencils = ((InventorySurrogated)obj).numpencils;
        invent.paper = ((InventorySurrogated)obj).numpaper;
        return invent;
    }
    return obj;
}

Diese Methode wird nur während der Deserialisierung eines Objekts aufgerufen.This method is called only during the deserialization of an object. Sie sorgt für die umgekehrte Datenzuordnung für die Deserialisierung vom Ersatzzeichentyp zum ursprünglichen Typ.It provides reverse data mapping for the deserialization from the surrogate type back to its original type. Wie bei der GetObjectToSerialize-Methode gehören zu den Anwendungsmöglichkeiten das direkte Austauschen von Felddaten, das Durchführen von Vorgängen an den Daten und das Speichern der XML-Daten.Similar to the GetObjectToSerialize method, some possible uses may be to directly exchange field data, perform operations on the data, and store XML data. Aufgrund von Änderungen während der Datenkonvertierung ergibt die Deserialisierung möglicherweise nicht immer die exakten Datenwerte aus dem Original.When deserializing, you may not always obtain the exact data values from original due to manipulations in the data conversion.

Der targetType-Parameter verweist auf den deklarierten Typ des Members.The targetType parameter refers to the declared type of the member. Dieser Parameter ist der Ersatzzeichentyp, der durch die GetDataContractType-Methode zurückgegeben wird.This parameter is the surrogated type returned by the GetDataContractType method. Die obj Parameter verweist auf das Objekt, das deserialisiert wurde.The obj parameter refers to the object that has been deserialized. Das Objekt kann zurück in seinen ursprünglichen Typ konvertiert werden, wenn es ersetzt wurde.The object can be converted back to its original type if it is surrogated. Diese Methode gibt den Eingabeobjekttyp zurück, wenn das Ersatzzeichen das Objekt nicht behandelt.This method returns the input object if the surrogate does not handle the object. Andernfalls wird das deserialisierte Objekt zurückgegeben, sobald seine Konvertierung abgeschlossen ist.Otherwise, the deserialized object will be returned once its conversion has been completed. Wenn verschiedene Ersatzzeichentypen existieren, können Sie für jeden dieser Typen die Datenkonvertierung vom Ersatzzeichentyp in den Primärtyp bewirken, indem Sie jeden Typ und dessen Konvertierung angeben.If several surrogate types exist, you may provide data conversion from surrogate to primary type for each by indicating each type and its conversion.

Beim Zurückgeben eines Objekts werden die internen Objekttabellen mit dem von diesem Ersatzzeichen zurückgegebenen Objekt aktualisiert.When returning an object, the internal object tables are updated with the object returned by this surrogate. Alle nachfolgenden Verweise auf eine Instanz rufen die Ersatzzeicheninstanz aus den Objekttabellen ab.Any subsequent references to an instance will obtain the surrogated instance from the object tables.

Im vorherigen Beispiel werden Objekte des Typs InventorySurrogated zurück in den ursprünglichen Typ Inventory konvertiert.The previous example converts objects of type InventorySurrogated back to the initial type Inventory. In diesem Fall werden die Daten direkt von InventorySurrogated auf seine entsprechenden Felder in Inventory zurückübertragen.In this case, data is directly transferred back from InventorySurrogated to its corresponding fields in Inventory. Da es keine Datenänderungen gibt, enthält jedes der Memberfelder dieselben Werte wie vor der Serialisierung.Because there are no data manipulations, the each of the member fields will contain the same values as before the serialization.

GetCustomDataToExport-MethodeGetCustomDataToExport Method

Beim Exportieren eines Schemas ist die GetCustomDataToExport-Methode optional.When exporting a schema, the GetCustomDataToExport method is optional. Sie wird verwendet, um zusätzliche Daten oder Hinweise in das exportierte Schema einzufügen.It is used to insert additional data or hints into the exported schema. Zusätzliche Daten können auf Memberebene oder auf Typebene eingefügt werden.Additional data can be inserted at the member level or type level. Zum Beispiel:For example:

public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
    Console.WriteLine("GetCustomDataToExport(Member)");
    System.Reflection.FieldInfo fieldInfo = (System.Reflection.FieldInfo)memberInfo;
    if (fieldInfo.IsPublic)
    {
        return "public";
    }
    else
    {
        return "private";
    }
}

Diese Methode (mit zwei Überladungen) ermöglicht die Einbeziehung zusätzlicher Informationen in die Metadaten auf der Member- oder der Typebene.This method (with two overloads) enables the inclusion of extra information into the metadata either at the member or type level. Damit ist es möglich, Hinweise dazu einzubeziehen, ob ein Member öffentlich oder privat ist, sowie Kommentare, die während des gesamten Exports und Imports des Schemas beibehalten werden.It is possible to include hints about whether a member is public or private, and comments which would be preserved throughout the export and import of the schema. Solche Informationen würden ohne diese Methode verloren gehen.Such information would be lost without this method. Diese Methode bewirkt nicht das Einfügen oder Löschen von Membern oder Typen, sondern fügt dem Schema auf diesen beiden Ebenen zusätzliche Daten hinzu.This method does not cause the insertion or deletion of members or types, but rather adds additional data to the schemas at either of these levels.

Die Methode wird überladen und kann entweder einen Type (clrtype-Parameter) oder MemberInfo (memberInfo-Parameter) nehmen.The method is overloaded and can take either a Type (clrtype parameter) or MemberInfo (memberInfo parameter). Der zweite Parameter ist immer ein Type (dataContractType-Parameter).The second parameter is always a Type (dataContractType parameter). Diese Methode wird für jeden Member und jeden Typ des ersetzten dataContractType-Typs aufgerufen.This method is called for every member and type of the surrogated dataContractType type.

Beide dieser Überladungen müssen entweder null oder ein serialisierbares Objekt zurückgeben.Either of these overloads must return either null or a serializable object. Ein Nicht-NULL-Objekt wird als Anmerkung in das exportierte Schema serialisiert.A non-null object will be serialized as annotation into the exported schema. Bei der Type-Überladung wird jeder Typ, der in das Schema exportiert wird, im ersten Parameter zusammen mit dem Ersatzzeichentyp als der dataContractType-Parameter zu dieser Methode gesendet.For the Type overload, each type that is exported to schema is sent to this method in the first parameter along with the surrogated type as the dataContractType parameter. Bei der MemberInfo-Überladung sendet jeder Member, der in das Schema exportiert wird, seine Informationen als den memberInfo-Parameter mit dem Ersatzzeichentyp im zweiten Parameter.For the MemberInfo overload, each member that is exported to schema sends its information as the memberInfo parameter with the surrogated type in the second parameter.

GetCustomDataToExport-Methode (Typ, Typ)GetCustomDataToExport Method (Type, Type)

Die IDataContractSurrogate.GetCustomDataToExport(Type, Type)-Methode wird während des Schemaexports für jede Typdefinition aufgerufen.The IDataContractSurrogate.GetCustomDataToExport(Type, Type) method is called during schema export for every type definition. Die Methode fügt den Typen innerhalb des Schemas beim Export Informationen hinzu.The method adds information to the types within the schema when exporting. Jeder definierte Typ wird zu dieser Methode gesendet, um zu überprüfen, ob es zusätzliche Daten gibt, die in das Schema einbezogen werden müssen.Each type defined is sent to this method to determine whether there is any additional data that needs to be included in the schema.

GetCustomDataToExport-Methode (MemberInfo, Typ)GetCustomDataToExport Method (MemberInfo, Type)

Die IDataContractSurrogate.GetCustomDataToExport(MemberInfo, Type)-Methode wird während des Exports für jeden Member in den Typen aufgerufen, die exportiert werden.The IDataContractSurrogate.GetCustomDataToExport(MemberInfo, Type) is called during export for every member in the types that are exported. Mit dieser Funktion können Sie alle Kommentare für die Member anpassen, die beim Export in das Schema aufgenommen werden.This function enables you to customize any comments for the members that will be included in the schema upon export. Die Informationen für jeden Member innerhalb der Klasse werden an diese Methode gesendet, um zu überprüfen, ob irgendwelche zusätzlichen Daten zum Schema hinzugefügt werden müssen.The information for every member within the class is sent to this method to check whether any additional data need to be added in the schema.

Das obige Beispiel durchsucht den dataContractType für jeden Member des Ersatzzeichens.The example above searches through the dataContractType for each member of the surrogate. Es gibt dann den entsprechenden Zugriffsmodifizierer für jedes Feld zurück.It then returns the appropriate access modifier for each field. Ohne diese Anpassung ist der Standardwert für Zugriffsmodifizierer öffentlich.Without this customization, the default value for access modifiers is public. Deshalb würden alle Member in dem mit dem exportierten Schema generierten Code als öffentlich definiert, und zwar unabhängig davon, welche tatsächlichen Zugriffsbeschränkungen für sie gelten.Therefore, all members would be defined as public in the code generated using the exported schema no matter what their actual access restrictions are. Wenn diese Implementierung nicht verwendet wird, wäre der Member numpens im exportierten Schema öffentlich, obwohl er im Ersatzzeichen als privat definiert wurde.When not using this implementation, the member numpens would be public in the exported schema even though it was defined in the surrogate as private. Durch die Verwendung dieser Methode kann der Zugriffsmodifizierer im exportierten Schema als privat generiert werden.Through the use of this method, in the exported schema, the access modifier can be generated as private.

GetReferencedTypeOnImport-MethodeGetReferencedTypeOnImport Method

Diese Methode ordnet dem ursprünglichen Typ den Type des Ersatzzeichens zu.This method maps the Type of the surrogate to the original type. Diese Methode ist für den Import von Schemas optional.This method is optional for schema importation.

Beim Erstellen eines Ersatzzeichens, das ein Schema importiert und für dieses Code generiert, besteht die nächste Aufgabe darin, den Typ einer Ersatzzeicheninstanz auf ihren ursprünglichen Typ festzulegen.When creating a surrogate that imports a schema and generates code for it, the next task is to define the type of a surrogate instance to its original type.

Wenn der generierte Code auf einen existierenden Benutzertyp verweisen muss, wird dies durch die Implementierung der GetReferencedTypeOnImport-Methode erreicht.If the generated code needs to reference an existing user type, this is done by implementing the GetReferencedTypeOnImport method.

Beim Importieren eines Schemas wird diese Methode für jede Typdeklaration aufgerufen, um einem Typ den Ersatzzeichen-Datenvertrag zuzuordnen.When importing a schema, this method is called for every type declaration to map the surrogated data contract to a type. Die Zeichenfolgenparameter typeName und typeNamespace definieren den Namen und den Namespace des Ersatzzeichentyps.The string parameters typeName and typeNamespace define the name and namespace of the surrogated type. Der Rückgabewert für GetReferencedTypeOnImport wird verwendet, um zu ermitteln, ob ein neuer Typ generiert werden muss.The return value for GetReferencedTypeOnImport is used to determine whether a new type needs to be generated. Diese Methode muss entweder einen gültigen Typ oder NULL zurückgeben.This method must return either a valid type or null. Für gültige Typen wird der zurückgegebene Typ im generierten Code als ein Typ verwendet, auf den verwiesen wird.For valid types, the type returned will be used as a referenced type in the generated code. Wenn NULL zurückgegeben wird, wird auf keinen Typ verwiesen, und ein neuer Typ muss erstellt werden.If null is returned, no type will be referenced and a new type must be created. Wenn mehrere Ersatzzeichen existieren, kann die Zuordnung für jeden Ersatzzeichentyp zurück zu seinem anfänglichen Typ durchgeführt werden.If several surrogates exist, it is possible to perform the mapping for each surrogate type back to its initial type.

Der customData-Parameter ist das Objekt, das ursprünglich von GetCustomDataToExport zurückgegeben wurde.The customData parameter is the object originally returned from GetCustomDataToExport. Dieser customData-Parameter wird verwendet, wenn Autoren von Ersatzzeichen zusätzliche Daten/Hinweise in die Metadaten einfügen möchten, um sie während des Imports zum Generieren von Code zu verwenden.This customData is used when surrogate authors want to insert extra data/hints into the metadata to use during import to generate code.

ProcessImportedType-MethodeProcessImportedType Method

Die ProcessImportedType-Methode passt jeden aus dem Schemaimport erstellten Typ an.The ProcessImportedType method customizes any type created from schema importation. Diese Methode ist optional.This method is optional.

Beim Importieren eines Schemas ermöglicht diese Methode die Anpassung jeder importierten Typ- und Kompilierungsinformation.When importing a schema, this method allows for any imported type and compilation information to be customized. Zum Beispiel:For example:

public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
    Console.WriteLine("ProcessImportedType");
    foreach (CodeTypeMember member in typeDeclaration.Members)
    {
        object memberCustomData = member.UserData[typeof(IDataContractSurrogate)];
        if (memberCustomData != null
          && memberCustomData is string
          && ((string)memberCustomData == "private"))
        {
            member.Attributes = ((member.Attributes & ~MemberAttributes.AccessMask) | MemberAttributes.Private);
        }
    }
    return typeDeclaration;
}

Während des Imports wird diese Methode für jeden generierten Typ aufgerufen.During import, this method is called for every type generated. Ändern der angegebenen CodeTypeDeclaration oder Ändern der CodeCompileUnit.Change the specified CodeTypeDeclaration or modify the CodeCompileUnit. Dies schließt das Ändern von Namen, Membern, Attributen und vielen anderen Eigenschaften der CodeTypeDeclaration ein.This includes changing the name, members, attributes, and many other properties of the CodeTypeDeclaration. Durch Verarbeiten der CodeCompileUnit ist es möglich, die Direktiven, die Namespaces, die referenzierten Assemblys und verschiedene andere Aspekte zu ändern.By processing the CodeCompileUnit, it is possible to modify the directives, namespaces, referenced assemblies, and several other aspects.

Der CodeTypeDeclaration-Parameter enthält die Code-DOM-Typdeklaration.The CodeTypeDeclaration parameter contains the code DOM type declaration. Der CodeCompileUnit-Parameter ermöglicht die Änderung zum Verarbeiten des Codes.The CodeCompileUnit parameter allows for modification for processing the code. Zurückgeben von null-Ergebnissen in der Typdeklaration, die verworfen wird.Returning null results in the type declaration being discarded. Umgekehrt werden beim Zurückgeben einer CodeTypeDeclaration die Änderungen beibehalten.Conversely, when returning a CodeTypeDeclaration, the modifications are preserved.

Wenn während des Metadatenexports benutzerdefinierte Daten eingefügt werden, müssen diese dem Benutzer beim Import so zur Verfügung gestellt werden, dass sie verwendet werden können.If custom data is inserted during metadata export, it needs to be provided to the user during import so that it can be used. Diese benutzerdefinierten Daten können zur Programmierung von Modellhinweisen oder anderen Kommentaren verwendet werden.This custom data can be used for programming model hints, or other comments. Jede CodeTypeDeclaration- und CodeTypeMember-Instanz schließt benutzerdefinierte Daten als die UserData-Eigenschaft ein, die in den IDataContractSurrogate-Typ umgewandelt wird.Each CodeTypeDeclaration and CodeTypeMember instance includes custom data as the UserData property, cast to the IDataContractSurrogate type.

Das obige Beispiel führt einige Änderungen an dem importierten Schema durch.The example above performs some changes on the schema imported. Der Code behält private Member des ursprünglichen Typs bei, indem ein Ersatzzeichen verwendet wird.The code preserves private members of the original type by using a surrogate. Der Standardzugriffsmodifizierer beim Importieren eines Schemas ist public.The default access modifier when importing a schema is public. Deshalb sind alle Member des Ersatzzeichenschemas öffentlich, es sei denn, es erfolgen Änderungen, wie in diesem Beispiel.Therefore, all members of the surrogate schema will be public unless modified, as in this example. Während des Exports werden in die Metadaten benutzerdefinierte Daten darüber eingefügt, welche Member privat sind.During export, custom data is inserted into the metadata about which members are private. Im Beispiel wird nach den benutzerdefinierten Daten gesucht, es wird überprüft, ob der Zugriffsmodifizierer privat ist, und der entsprechende Member wird dann durch Festlegen seiner Attribute zu privat geändert.The example looks up the custom data, checks whether the access modifier is private, and then modifies the appropriate member to be private by setting its attributes. Ohne diese Anpassung würde der numpens-Member nicht als privat, sondern als öffentlich definiert werden.Without this customization, the numpens member would be defined as public instead of private.

GetKnownCustomDataTypes-MethodeGetKnownCustomDataTypes Method

Diese Methode gewinnt aus dem Schema definierte benutzerdefinierte Datentypen.This method obtains custom data types defined from the schema. Die Methode ist für den Import von Schemas optional.The method is optional for schema importation.

Die Methode wird zu Beginn des Schemaexports und -imports aufgerufen.The method is called at the beginning of schema export and import. Die Methode gibt die benutzerdefinierten Datentypen zurück, die im exportierten oder importierten Schema verwendet werden.The method returns the custom data types used in the schema exported or imported. An die Methode wird ein Collection<T> übergeben (der customDataTypes), wobei es sich um eine Sammlung von Typen handelt.The method is passed a Collection<T> (the customDataTypes parameter), which is a collection of types. Die Methode sollte dieser Sammlung zusätzliche bekannte Typen hinzufügen.The method should add additional known types to this collection. Die bekannten benutzerdefinierten Datentypen werden benötigt, um die Serialisierung und Deserialisierung von benutzerdefinierten Daten mit dem DataContractSerializer zu ermöglichen.The known custom data types are needed to enable serialization and deserialization of custom data using the DataContractSerializer. Weitere Informationen finden Sie unter Datenvertragstypen bezeichnet.For more information, see Data Contract Known Types.

Implementieren eines ErsatzzeichensImplementing a Surrogate

Um dem Datenvertrag-Ersatzzeichen innerhalb von WCF verwenden zu können, müssen Sie einige besondere Prozeduren befolgen.To use the data contract surrogate within WCF, you must follow a few special procedures.

So verwenden Sie ein Ersatzzeichen für die Serialisierung und DeserialisierungTo Use a Surrogate for Serialization and Deserialization

Verwenden Sie das DataContractSerializer, um die Serialisierung und die Deserialisierung von Daten mit dem Ersatzzeichen durchzuführen.Use the DataContractSerializer to perform serialization and deserialization of data with the surrogate. Das DataContractSerializer wird durch das DataContractSerializerOperationBehavior erstellt.The DataContractSerializer is created by the DataContractSerializerOperationBehavior. Das Ersatzzeichen muss ebenfalls angegeben werden.The surrogate must also be specified.

So implementieren Sie die Serialisierung und die DeserialisierungTo implement serialization and deserialization
  1. Erstellen Sie eine Instanz des ServiceHost für Ihren Dienst.Create an instance of the ServiceHost for your service. Vollständige Anweisungen finden Sie unter grundlegende WCF-Programmierung.For complete instructions, see Basic WCF Programming.

  2. Suchen Sie für jeden ServiceEndpoint des angegebenen Diensthosts seine OperationDescription.For every ServiceEndpoint of the specified service host, find its OperationDescription.

  3. Durchsuchen Sie die Vorgangsverhalten, um zu ermitteln, ob eine Instanz von DataContractSerializerOperationBehavior gefunden wird.Search through the operation behaviors to determine if an instance of the DataContractSerializerOperationBehavior is found.

  4. Wenn ein DataContractSerializerOperationBehavior gefunden wird, legen Sie dessen DataContractSurrogate-Eigenschaft auf eine neue Instanz des Ersatzzeichens fest.If a DataContractSerializerOperationBehavior is found, set its DataContractSurrogate property to a new instance of the surrogate. Wenn kein DataContractSerializerOperationBehavior gefunden wird, dann erstellen Sie eine neue Instanz, und legen Sie den DataContractSurrogate-Member des neuen Verhaltens auf eine neue Instanz des Ersatzzeichens fest.If no DataContractSerializerOperationBehavior is found, then create a new instance and set the DataContractSurrogate member of the new behavior to a new instance of the surrogate.

  5. Fügen Sie dieses neue Verhalten schließlich den aktuellen Vorgangsverhalten hinzu, wie im folgenden Beispiel gezeigt wird:Finally, add this new behavior to the current operation behaviors, as shown in the following example:

    using (ServiceHost serviceHost = new ServiceHost(typeof(InventoryCheck)))
        foreach (ServiceEndpoint ep in serviceHost.Description.Endpoints)
        {
            foreach (OperationDescription op in ep.Contract.Operations)
            {                       
                DataContractSerializerOperationBehavior dataContractBehavior =
                    op.Behaviors.Find<DataContractSerializerOperationBehavior>()
                    as DataContractSerializerOperationBehavior;
                if (dataContractBehavior != null)
                {
                    dataContractBehavior.DataContractSurrogate = new InventorySurrogated();
                }
                else
                {
                    dataContractBehavior = new DataContractSerializerOperationBehavior(op);
                    dataContractBehavior.DataContractSurrogate = new InventorySurrogated();
                    op.Behaviors.Add(dataContractBehavior);
                }
            }
        }
    

So verwenden Sie ein Ersatzzeichen für den MetadatenimportTo Use a Surrogate for Metadata Import

Beim Importieren von Metadaten wie WSDL und XSD zum Generieren von clientseitigem Code muss das Ersatzzeichen zur Komponente XsdDataContractImporter, die für das Generieren von Code aus dem XSD-Schema verantwortlich ist, hinzugefügt werden.When importing metadata like WSDL and XSD to generate client-side code, the surrogate needs to be added to the component responsible for generating code from XSD schema, XsdDataContractImporter. Dazu ändern Sie direkt den zum Importieren von Metadaten verwendeten WsdlImporter.To do this, directly modify the WsdlImporter used to import metadata.

So implementieren Sie ein Ersatzzeichen für den MetadatenimportTo implement a surrogate for metadata importation
  1. Importieren Sie die Metadaten mit der WsdlImporter-Klasse.Import the metadata using the WsdlImporter class.

  2. Verwenden Sie die TryGetValue-Methode zur Überprüfung, ob ein XsdDataContractImporter definiert wurde.Use the TryGetValue method to check whether an XsdDataContractImporter has been defined.

  3. Wenn die TryGetValue-Methode false zurückgibt, erstellen Sie einen neuen XsdDataContractImporter, und legen Sie dessen Options-Eigenschaft auf eine neue Instanz der ImportOptions-Klasse fest.If the TryGetValue method returns false, create a new XsdDataContractImporter and set its Options property to a new instance of the ImportOptions class. Verwenden Sie andernfalls den durch den out-Parameter der TryGetValue-Methode zurückgegebenen Importer.Otherwise, use the importer returned by the out parameter of the TryGetValue method.

  4. Wenn für den XsdDataContractImporter keine ImportOptions definiert sind, dann legen Sie die Eigenschaft auf eine neue Instanz der ImportOptions-Klasse fest.If the XsdDataContractImporter has no ImportOptions defined, then set the property to be a new instance of the ImportOptions class.

  5. Legen Sie die DataContractSurrogate-Eigenschaft der ImportOptions des XsdDataContractImporter auf eine neue Instanz des Ersatzzeichens fest.Set the DataContractSurrogate property of the ImportOptions of the XsdDataContractImporter to a new instance of the surrogate.

  6. Fügen Sie den XsdDataContractImporter der Sammlung hinzu, die durch die State-Eigenschaft des WsdlImporter (geerbt von der MetadataExporter-Klasse) zurückgegeben wird.Add the XsdDataContractImporter to the collection returned by the State property of the WsdlImporter (inherited from the MetadataExporter class.)

  7. Verwenden Sie die ImportAllContracts-Methode des WsdlImporter zum Importieren sämtlicher Datenverträge innerhalb des Schemas.Use the ImportAllContracts method of the WsdlImporter to import all of the data contracts within the schema. Während des letzten Schritts wird Code aus den geladenen Schemas durch Aufruf in das Ersatzzeichen generiert.During the last step, code is generated from the schemas loaded by calling into the surrogate.

    MetadataExchangeClient mexClient = new MetadataExchangeClient(metadataAddress);
    mexClient.ResolveMetadataReferences = true;
    MetadataSet metaDocs = mexClient.GetMetadata();
    WsdlImporter importer = new WsdlImporter(metaDocs);
    object dataContractImporter;
    XsdDataContractImporter xsdInventoryImporter;
    if (!importer.State.TryGetValue(typeof(XsdDataContractImporter),
        out dataContractImporter))
        xsdInventoryImporter = new XsdDataContractImporter();
    
    xsdInventoryImporter = (XsdDataContractImporter)dataContractImporter;
    if (xsdInventoryImporter.Options == null)
    {
        xsdInventoryImporter.Options = new ImportOptions();
    }
    xsdInventoryImporter.Options.DataContractSurrogate = new InventorySurrogated();
    importer.State.Add(typeof(XsdDataContractImporter), xsdInventoryImporter);
    
    Collection<ContractDescription> contracts = importer.ImportAllContracts();
    

So verwenden Sie ein Ersatzzeichen für den MetadatenexportTo Use a surrogate for Metadata Export

Wird standardmäßig beim Exportieren von Metadaten von WCF für einen Dienst muss WSDL- und XSD-Schema generiert werden soll.By default, when exporting metadata from WCF for a service, both WSDL and XSD schema needs to be generated. Das Ersatzzeichen muss der Komponente XsdDataContractExporter hinzugefügt werden, die für das Generieren des XSD-Schemas für Datenvertragstypen verantwortlich ist.The surrogate needs to be added to the component responsible for generating XSD schema for data contract types, XsdDataContractExporter. Dazu verwenden Sie entweder ein Verhalten, das IWsdlExportExtension implementiert, um das WsdlExporter zu ändern, oder ändern Sie das zum Exportieren von Metadaten verwendete WsdlExporter direkt.To do this, either use a behavior that implements IWsdlExportExtension to modify the WsdlExporter, or directly modify the WsdlExporter used to export metadata.

So verwenden Sie ein Ersatzzeichen für den MetadatenexportTo use a surrogate for metadata export
  1. Erstellen Sie ein neues WsdlExporter, oder verwenden Sie den wsdlExporter-Parameter, der an die ExportContract-Methode übergeben wird.Create a new WsdlExporter or use the wsdlExporter parameter passed to the ExportContract method.

  2. Verwenden Sie die TryGetValue-Funktion zur Überprüfung, ob ein XsdDataContractExporter definiert wurde.Use the TryGetValue function to check whether an XsdDataContractExporter has been defined.

  3. Wenn TryGetValue false zurückgibt, erstellen Sie ein neues XsdDataContractExporter mit den generierten XML-Schemas aus dem WsdlExporter, und fügen Sie diesen der Sammlung hinzu, die durch die State-Eigenschaft des WsdlExporter zurückgegeben wird.If TryGetValue returns false, create a new XsdDataContractExporter with the generated XML schemas from the WsdlExporter, and add it to the collection returned by the State property of the WsdlExporter. Verwenden Sie andernfalls das Exportprogramm, das durch den out-Parameter der TryGetValue-Methode zurückgegeben wird.Otherwise, use the exporter returned by the out parameter of the TryGetValue method.

  4. Wenn für das XsdDataContractExporter keine ExportOptions definiert sind, dann legen Sie die Options-Eigenschaft auf eine neue Instanz der ExportOptions-Klasse fest.If the XsdDataContractExporter has no ExportOptions defined, then set the Options property to a new instance of the ExportOptions class.

  5. Legen Sie die DataContractSurrogate-Eigenschaft der ExportOptions des XsdDataContractExporter auf eine neue Instanz des Ersatzzeichens fest.Set the DataContractSurrogate property of the ExportOptions of the XsdDataContractExporter to a new instance of the surrogate. Die nachfolgenden Schritte zum Exportieren von Metadaten erfordern keine Änderungen.Subsequent steps for exporting metadata do not require any changes.

    WsdlExporter exporter = new WsdlExporter();
    //or
    //public void ExportContract(WsdlExporter exporter, 
    // WsdlContractConversionContext context) { ... }
    object dataContractExporter;
    XsdDataContractExporter xsdInventoryExporter;
    if (!exporter.State.TryGetValue(typeof(XsdDataContractExporter),
        out dataContractExporter))
    {
        xsdInventoryExporter = new XsdDataContractExporter(exporter.GeneratedXmlSchemas);
    }
    else
        xsdInventoryExporter = (XsdDataContractExporter)dataContractExporter;
    exporter.State.Add(typeof(XsdDataContractExporter), xsdInventoryExporter);
    
    
    
    if (xsdInventoryExporter.Options == null)
        xsdInventoryExporter.Options = new ExportOptions();
    xsdInventoryExporter.Options.DataContractSurrogate = new InventorySurrogated();
    

Siehe auchSee Also

DataContractSerializer
IDataContractSurrogate
DataContractSerializerOperationBehavior
ImportOptions
ExportOptions
Verwenden von DatenverträgenUsing Data Contracts