Substituts de contrats de donnéesData Contract Surrogates

Le substitut de contrat de données est une fonctionnalité avancée basée sur le modèle de contrat de données.The data contract surrogate is an advanced feature built upon the Data Contract model. Cette fonctionnalité est destinée à la personnalisation et à la substitution de type dans les situations où les utilisateurs souhaitent changer la manière dont un type est sérialisé, désérialisé ou projeté dans des métadonnées.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. On peut par exemple utiliser un substitut lorsque aucun contrat de données n'a été spécifié pour le type, que les champs et propriétés ne sont pas marqués avec l'attribut DataMemberAttribute ou que les utilisateurs souhaitent créer des variations de schéma de manière dynamique.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.

La sérialisation et la désérialisation sont accomplies avec le substitut de contrat de données lors de l’utilisation de DataContractSerializer pour effectuer la conversion à partir du .NET Framework vers un format approprié, tel que XML.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. Le substitut de contrat de données peut également être utilisé pour modifier les métadonnées exportées pour les types, lors de la production de représentations de métadonnées telles que des documents XSD (XML Schema Documents).Data contract surrogate can also be used to modify the metadata exported for types, when producing metadata representations such as XML Schema Documents (XSD). Lors de l'importation, le code est créé à partir des métadonnées et le substitut peut être utilisé dans ce cas pour personnaliser également le code généré.Upon import, code is created from metadata and the surrogate can be used in this case to customize the generated code as well.

Fonctionnement du substitutHow the Surrogate Works

Un substitut mappe un type (le type « d'origine ») à un autre type (le type « substitué »).A surrogate works by mapping one type (the "original" type) to another type (the "surrogated" type). L'exemple suivant illustre le type Inventory d'origine et un nouveau type InventorySurrogated de substitution.The following example shows the original type Inventory and a new surrogate InventorySurrogated type. Le type Inventory n'est pas sérialisable, mais le type InventorySurrogated l'est :The Inventory type is not serializable but the InventorySurrogated type is:

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

Aucun contrat de données n'ayant été défini pour cette classe, vous devez convertir la classe en une classe de substitution avec un contrat de données.Because a data contract has not been defined for this class, convert the class to a surrogate class with a data contract. La classe de substitution est illustrée dans l'exemple suivant :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; }
    }
}

Implémentation de l'IDataContractSurrogateImplementing the IDataContractSurrogate

Pour utiliser le substitut de contrat de données, implémentez l'interface IDataContractSurrogate.To use the data contract surrogate, implement the IDataContractSurrogate interface.

Vous trouverez ci-dessous une vue d'ensemble de chaque méthode de IDataContractSurrogate avec une implémentation possible.The following is an overview of each method of IDataContractSurrogate with a possible implementation.

GetDataContractTypeGetDataContractType

La méthode GetDataContractType établit une correspondance entre les types.The GetDataContractType method maps one type to another. Cette méthode est requise pour la sérialisation, la désérialisation, l'importation et l'exportation.This method is required for serialization, deserialization, import, and export.

La première tâche consiste à définir les types qui seront mappés à d'autres types.The first task is defining what types will be mapped to other types. Par exemple :For example:

public Type GetDataContractType(Type type)
{
    Console.WriteLine("GetDataContractType");
    if (typeof(Inventory).IsAssignableFrom(type))
    {
        return typeof(InventorySurrogated);
    }
    return type;
}
  • Lors de la sérialisation, le mappage retourné par cette méthode est utilisé par la suite pour transformer l'instance d'origine en une instance de substitution en appelant la méthode GetObjectToSerialize.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.

  • Lors de la désérialisation, le mappage retourné par cette méthode est utilisé par le sérialiseur afin de désérialiser en une instance du type de substitution.On deserialization, the mapping returned by this method is used by the serializer to deserialize into an instance of the surrogate type. La méthode appelle par la suite GetDeserializedObject pour transformer l'instance substituée en une instance du type d'origine.It subsequently calls GetDeserializedObject to transform the surrogated instance into an instance of the original type.

  • Lors de l'exportation, le type de substitution retourné par cette méthode est reflété afin d'obtenir le contrat de données à utiliser pour générer les métadonnées.On export, the surrogate type returned by this method is reflected to get the data contract to use for generating metadata.

  • Lors de l'importation, le type initial est modifié en un type de substitution qui est reflété afin d'obtenir le contrat de données à utiliser à des fins telles que le référencement de prise en charge.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.

Le paramètre Type est le type de l'objet sérialisé, désérialisé, importé ou exporté.The Type parameter is the type of the object that is being serialized, deserialized, imported, or exported. La méthode GetDataContractType doit retourner le type d'entrée si le substitut ne gère pas le type.The GetDataContractType method must return the input type if the surrogate does not handle the type. Autrement, retournez le type substitué approprié.Otherwise, return the appropriate surrogated type. S'il existe plusieurs types de substitution, de nombreux mappages peuvent être définis dans cette méthode.If several surrogate types exist, numerous mappings can be defined in this method.

La méthode GetDataContractType n'est pas appelée pour les primitives de contrat de données intégrées, telles que Int32 ou String.The GetDataContractType method is not called for built-in data contract primitives, such as Int32 or String. Pour d'autres types, tels que les tableaux, les types définis par l'utilisateur et autres structures de données, cette méthode sera appelée pour chaque type.For other types, such as arrays, user-defined types, and other data structures, this method will be called for each type.

Dans l'exemple précédent, la méthode vérifie si les paramètres type et Inventory sont comparables.In the previous example, the method checks if the type parameter and Inventory are comparable. Si c'est le cas, la méthode le mappe à InventorySurrogated.If so, the method maps it to InventorySurrogated. Chaque fois qu’une sérialisation, une désérialisation, un schéma d’importation ou un schéma d’exportation est appelé(e), cette fonction est appelée en premier afin de déterminer le mappage entre les types.Whenever a serialization, deserialization, import schema, or export schema is called, this function is called first to determine the mapping between types.

Méthode GetObjectToSerializeGetObjectToSerialize Method

La méthode GetObjectToSerialize convertit l'instance de type d'origine en instance de type substitué.The GetObjectToSerialize method converts the original type instance to the surrogated type instance. La méthode est requise pour la sérialisation.The method is required for serialization.

L'étape suivante consiste à définir la façon dont les données physiques seront mappées de l'instance d'origine au substitut en implémentant la méthode GetObjectToSerialize.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. Par exemple :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;
}

La méthode GetObjectToSerialize est appelée lorsqu'un objet est sérialisé.The GetObjectToSerialize method is called when an object is serialized. Cette méthode transfère des données du type d'origine aux champs du type substitué.This method transfers data from the original type to the fields of the surrogated type. Les champs peuvent être mappés directement à des champs de substitution, ou des manipulations des données d'origine peuvent être stockées dans le substitut.Fields can be directly mapped to surrogate fields, or manipulations of the original data may be stored in the surrogate. Certaines utilisations possibles incluent : mappage direct des champs, exécution d'opérations sur les données à stocker dans les champs substitués, ou stockage du XML du type d'origine dans le champ substitué.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.

Le paramètre targetType fait référence au type déclaré du membre.The targetType parameter refers to the declared type of the member. Ce paramètre est le type substitué retourné par la méthode GetDataContractType.This parameter is the surrogated type returned by the GetDataContractType method. Le sérialiseur n'applique pas l'impératif selon lequel l'objet retourné doit être assignable à ce type.The serializer does not enforce that the object returned is assignable to this type. Le obj paramètre est l’objet à sérialiser et est converti en son substitut, si nécessaire.The obj parameter is the object to serialize, and will be converted to its surrogate if necessary. Cette méthode doit retourner l'objet d'entrée si le substitué ne gère pas l'objet.This method must return the input object if the surrogated does not handle the object. Autrement, le nouvel objet de substitution sera retourné.Otherwise, the new surrogate object will be returned. Le substitut n'est pas appelé si l'objet est null.The surrogate is not called if the object is null. Plusieurs mappages de substitution pour différentes instances peuvent être définis dans cette méthode.Numerous surrogate mappings for different instances may be defined within this method.

Lorsque vous créez un DataContractSerializer, vous pouvez faire en sorte qu'il conserve les références d'objets.When creating a DataContractSerializer, you can instruct it to preserve object references. (Pour plus d’informations, consultez sérialisation et désérialisation.) Vous devez pour cela affecter au paramètre preserveObjectReferences dans son constructeur la valeur true.(For more information, see Serialization and Deserialization.) This is done by setting the preserveObjectReferences parameter in its constructor to true. Dans ce cas, le substitut est appelé une seule fois pour un objet puisque toutes les sérialisations suivantes écrivent simplement la référence dans le flux.In that case, the surrogate is called only once for an object since all subsequent serializations just write the reference into the stream. Si preserveObjectReferences a la valeur false, le substitut est appelé chaque fois qu'une instance est rencontrée.If preserveObjectReferences is set to false, then the surrogate is called every time an instance is encountered.

Si le type de l'instance sérialisé diffère du type déclaré, les informations de type sont écrites dans le flux, par exemple xsi:type pour autoriser l'instance à être désérialisée à l'autre extrémité.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. Ce processus se produit que l'objet soit substitué ou non.This process occurs whether the object is surrogated or not.

L'exemple ci-dessus convertit les données de l'instance Inventory en données InventorySurrogated.The example above converts the data of the Inventory instance to that of InventorySurrogated. Il vérifie le type de l'objet et effectue les manipulations nécessaires pour effectuer la conversion au type substitué.It checks the type of the object and performs the necessary manipulations to convert to the surrogated type. Dans ce cas, les champs de la classe Inventory sont copiés directement vers les champs de la classe InventorySurrogated.In this case, the fields of the Inventory class are directly copied over to the InventorySurrogated class fields.

Méthode GetDeserializedObjectGetDeserializedObject Method

La méthode GetDeserializedObject convertit l'instance de type substitué en instance de type d'origine.The GetDeserializedObject method converts the surrogated type instance to the original type instance. Elle est requise pour la désérialisation.It is required for deserialization.

La tâche suivante consiste à définir la façon dont les données physiques seront mappées de l’instance de substitution à l’original.The next task is to define the way the physical data will be mapped from the surrogate instance to the original. Par exemple :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;
}

Cette méthode est appelée uniquement pendant la désérialisation d'un objet.This method is called only during the deserialization of an object. Elle fournit un mappage de données inverse pour la désérialisation du type de substitution à son type d'origine.It provides reverse data mapping for the deserialization from the surrogate type back to its original type. Elle est semblable à la méthode GetObjectToSerialize, et on peut l'utiliser afin d'échanger directement des données de champs, effectuer des opérations sur les données et stocker des données XML.Similar to the GetObjectToSerialize method, some possible uses may be to directly exchange field data, perform operations on the data, and store XML data. Lors de la désérialisation, vous risquez de ne pas toujours obtenir les valeurs de données exactes de l'original en raison des manipulations liées à la conversion des données.When deserializing, you may not always obtain the exact data values from original due to manipulations in the data conversion.

Le paramètre targetType fait référence au type déclaré du membre.The targetType parameter refers to the declared type of the member. Ce paramètre est le type substitué retourné par la méthode GetDataContractType.This parameter is the surrogated type returned by the GetDataContractType method. Le obj paramètre fait référence à l’objet qui a été désérialisé.The obj parameter refers to the object that has been deserialized. L'objet peut être reconverti en son type d'origine s'il est substitué.The object can be converted back to its original type if it is surrogated. Cette méthode retourne l'objet d'entrée si le substitue ne gère pas l'objet.This method returns the input object if the surrogate does not handle the object. Autrement, l'objet désérialisé sera retourné une fois sa conversion achevée.Otherwise, the deserialized object will be returned once its conversion has been completed. S'il existe plusieurs types de substitution, vous pouvez fournir la conversion de données du type de substitution au type principal pour chacun d'entre eux en indiquant chaque type et sa conversion.If several surrogate types exist, you may provide data conversion from surrogate to primary type for each by indicating each type and its conversion.

Lors du retour d'un objet, les tables d'objets internes sont mises à jour avec l'objet retourné par ce substitut.When returning an object, the internal object tables are updated with the object returned by this surrogate. Toute référence ultérieure à une instance obtiendra l'instance substituée à partir des tables d'objets.Any subsequent references to an instance will obtain the surrogated instance from the object tables.

L'exemple précédent reconvertit des objets de type InventorySurrogated en type Inventory initial.The previous example converts objects of type InventorySurrogated back to the initial type Inventory. Dans ce cas, les données sont retransférées directement à partir de InventorySurrogated vers ses champs correspondants dans Inventory.In this case, data is directly transferred back from InventorySurrogated to its corresponding fields in Inventory. Étant donné qu'il n'y a pas de manipulations de données, chacun des champs membres contiendra les mêmes valeurs qu'avant la sérialisation.Because there are no data manipulations, the each of the member fields will contain the same values as before the serialization.

Méthode GetCustomDataToExportGetCustomDataToExport Method

Lors de l'exportation d'un schéma, la méthode GetCustomDataToExport est facultative.When exporting a schema, the GetCustomDataToExport method is optional. Elle est utilisée pour insérer des conseils ou des données supplémentaires dans le schéma exporté.It is used to insert additional data or hints into the exported schema. Les données supplémentaires peuvent être insérées au niveau du membre ou au niveau du type.Additional data can be inserted at the member level or type level. Par exemple :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";
    }
}

Cette méthode (avec deux surcharges) autorise l'inclusion d'informations supplémentaires dans les métadonnées au niveau du membre ou au niveau du type.This method (with two overloads) enables the inclusion of extra information into the metadata either at the member or type level. Il est possible d'inclure des conseils relatifs au caractère public ou privé d'un membre et des commentaires qui seraient conservés durant toute l'exportation et l'importation du schéma.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. De telles informations seraient perdues sans cette méthode.Such information would be lost without this method. Cette méthode ne provoque pas l'insertion ou la suppression de membres ou de types, mais elle ajoute plutôt des données supplémentaires aux schémas à l'un ou l'autre de ces niveaux.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.

La méthode est surchargée et peut prendre un Type (paramètre clrtype) ou un MemberInfo (paramètre memberInfo).The method is overloaded and can take either a Type (clrtype parameter) or MemberInfo (memberInfo parameter). Le deuxième paramètre est toujours un Type (paramètre dataContractType).The second parameter is always a Type (dataContractType parameter). Cette méthode est appelée pour chaque membre et type du type dataContractType substitué.This method is called for every member and type of the surrogated dataContractType type.

L'une ou l'autre de ces surcharges doit retourner null ou un objet sérialisable.Either of these overloads must return either null or a serializable object. Un objet non null sera sérialisé comme annotation dans le schéma exporté.A non-null object will be serialized as annotation into the exported schema. Pour la surcharge Type, chaque type exporté vers le schéma est envoyé à cette méthode dans le premier paramètre avec le type substitué comme paramètre dataContractType.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. Pour la surcharge MemberInfo, chaque membre exporté vers le schéma envoie ses informations comme paramètre memberInfo avec le type substitué dans le deuxième paramètre.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.

Méthode GetCustomDataToExport (Type, Type)GetCustomDataToExport Method (Type, Type)

La méthode IDataContractSurrogate.GetCustomDataToExport(Type, Type) est appelée pendant l'exportation de schéma pour chaque définition de type.The IDataContractSurrogate.GetCustomDataToExport(Type, Type) method is called during schema export for every type definition. La méthode ajoute des informations aux types dans le schéma lors de l'exportation.The method adds information to the types within the schema when exporting. Chaque type défini est envoyé à cette méthode pour déterminer si des données supplémentaires doivent être incluses dans le schéma.Each type defined is sent to this method to determine whether there is any additional data that needs to be included in the schema.

Méthode GetCustomDataToExport (MemberInfo, Type)GetCustomDataToExport Method (MemberInfo, Type)

Le IDataContractSurrogate.GetCustomDataToExport(MemberInfo, Type) est appelé pendant l'exportation pour chaque membre dans les types exportés.The IDataContractSurrogate.GetCustomDataToExport(MemberInfo, Type) is called during export for every member in the types that are exported. Cette fonction vous permet de personnaliser tout commentaire pour les membres qui seront inclus dans le schéma lors de l'exportation.This function enables you to customize any comments for the members that will be included in the schema upon export. Les informations pour chaque membre dans la classe sont envoyées à cette méthode afin de vérifier si des données supplémentaires doivent être ajoutées dans le schéma.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.

L'exemple suivant recherche dans le dataContractType pour chaque membre du substitut.The example above searches through the dataContractType for each member of the surrogate. Il retourne ensuite le modificateur d’accès approprié pour chaque champ.It then returns the appropriate access modifier for each field. Sans cette personnalisation, la valeur par défaut pour les modificateurs d’accès est publique.Without this customization, the default value for access modifiers is public. Par conséquent, tous les membres seraient définis comme publics dans le code généré à l'aide du schéma exporté, quelles que soient leurs restrictions d'accès réelles.Therefore, all members would be defined as public in the code generated using the exported schema no matter what their actual access restrictions are. Si cette implémentation n'était pas utilisée, le membre numpens serait public dans le schéma exporté bien qu'il ait été défini comme privé dans le substitut.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. Grâce à l'utilisation de cette méthode, dans le schéma exporté, le modificateur d'accès peut être généré comme privé.Through the use of this method, in the exported schema, the access modifier can be generated as private.

Méthode GetReferencedTypeOnImportGetReferencedTypeOnImport Method

Cette méthode mappe le Type du substitut au type d'origine.This method maps the Type of the surrogate to the original type. Cette méthode est facultative pour l'importation de schéma.This method is optional for schema importation.

Lors de la création d’un substitut qui importe un schéma et génère le code pour celui-ci, la tâche suivante consiste à définir le type d’une instance de substitution à son type d’origine.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.

Si le code généré doit faire référence à un type utilisateur existant, cette opération est effectuée en implémentant la méthode GetReferencedTypeOnImport.If the generated code needs to reference an existing user type, this is done by implementing the GetReferencedTypeOnImport method.

Lors de l'importation d'un schéma, cette méthode est appelée pour chaque déclaration de type afin de mapper le contrat de données substitué à un type.When importing a schema, this method is called for every type declaration to map the surrogated data contract to a type. Les paramètres chaîne typeName et typeNamespace définissent le nom et l'espace de noms du type substitué.The string parameters typeName and typeNamespace define the name and namespace of the surrogated type. La valeur de retour pour GetReferencedTypeOnImport est utilisée pour déterminer si un nouveau type doit être généré.The return value for GetReferencedTypeOnImport is used to determine whether a new type needs to be generated. Cette méthode doit retourner un type valide ou null.This method must return either a valid type or null. Pour les types valides, le type retourné sera utilisé en tant que type référencé dans le code généré.For valid types, the type returned will be used as a referenced type in the generated code. Si null est retourné, aucun type ne sera référencé et un nouveau type doit être créé.If null is returned, no type will be referenced and a new type must be created. S'il existe plusieurs substituts, il est possible d'effectuer le mappage pour chaque type de substitution vers son type initial.If several surrogates exist, it is possible to perform the mapping for each surrogate type back to its initial type.

Le paramètre customData est l'objet initialement retourné à partir de GetCustomDataToExport.The customData parameter is the object originally returned from GetCustomDataToExport. Ce customData est utilisé lorsque des auteurs de substitution souhaitent insérer des données/conseils supplémentaires dans les métadonnées pour une utilisation pendant l'importation afin de générer le code.This customData is used when surrogate authors want to insert extra data/hints into the metadata to use during import to generate code.

Méthode ProcessImportedTypeProcessImportedType Method

La méthode ProcessImportedType personnalise tout type créé à partir de l'importation de schéma.The ProcessImportedType method customizes any type created from schema importation. Cette méthode est facultative.This method is optional.

Lors de l'importation d'un schéma, cette méthode permet de personnaliser tout type importé et toute information de compilation.When importing a schema, this method allows for any imported type and compilation information to be customized. Par exemple :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;
}

Durant l'importation, cette méthode est appelée pour chaque type généré.During import, this method is called for every type generated. Modifiez le CodeTypeDeclaration spécifié ou modifiez le CodeCompileUnit.Change the specified CodeTypeDeclaration or modify the CodeCompileUnit. Cela inclut la modification du nom, des membres, des attributs et de nombreuses autres propriétés du CodeTypeDeclaration.This includes changing the name, members, attributes, and many other properties of the CodeTypeDeclaration. En traitant le CodeCompileUnit, il est possible de modifier les directives, espaces de noms, assemblys référencés et plusieurs autres aspects.By processing the CodeCompileUnit, it is possible to modify the directives, namespaces, referenced assemblies, and several other aspects.

Le paramètre CodeTypeDeclaration contient la déclaration de type DOM de code.The CodeTypeDeclaration parameter contains the code DOM type declaration. Le paramètre CodeCompileUnit autorise la modification pour le traitement du code.The CodeCompileUnit parameter allows for modification for processing the code. Le retour de null entraîne le rejet de la déclaration de type.Returning null results in the type declaration being discarded. Inversement, lors du retour d'un CodeTypeDeclaration, les modifications sont conservées.Conversely, when returning a CodeTypeDeclaration, the modifications are preserved.

Si des données personnalisées sont insérées pendant l'exportation des métadonnées, elles doivent être fournies à l'utilisateur pendant l'importation afin de pouvoir être utilisées.If custom data is inserted during metadata export, it needs to be provided to the user during import so that it can be used. Ces données personnalisées peuvent être utilisées pour des conseils de modèle de programmation ou autres commentaires.This custom data can be used for programming model hints, or other comments. Chaque instance CodeTypeDeclaration et CodeTypeMember inclut des données personnalisées en tant que propriété UserData, faisant l'objet d'un cast en type IDataContractSurrogate.Each CodeTypeDeclaration and CodeTypeMember instance includes custom data as the UserData property, cast to the IDataContractSurrogate type.

L'exemple ci-dessus apporte des modifications au schéma importé.The example above performs some changes on the schema imported. Le code conserve des membres privés du type d'origine en utilisant un substitut.The code preserves private members of the original type by using a surrogate. Le modificateur d’accès par défaut lors de l’importation d’un schéma est public.The default access modifier when importing a schema is public. Par conséquent, tous les membres du schéma de substitution seront publics à moins d'être modifiés, comme dans cet exemple.Therefore, all members of the surrogate schema will be public unless modified, as in this example. Pendant l'exportation, des données personnalisées sont insérées dans les métadonnées à propos des membres privés.During export, custom data is inserted into the metadata about which members are private. L’exemple consulte les données personnalisées, vérifie si le modificateur d’accès est privé, puis rend le membre approprié privé en définissant ses attributs.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. Sans cette personnalisation, le membre numpens serait défini comme public au lieu de privé.Without this customization, the numpens member would be defined as public instead of private.

Méthode GetKnownCustomDataTypesGetKnownCustomDataTypes Method

Cette méthode obtient des types de données personnalisés définis à partir du schéma.This method obtains custom data types defined from the schema. Elle est facultative pour l'importation de schéma.The method is optional for schema importation.

La méthode est appelée au début de l'exportation et de l'importation de schéma.The method is called at the beginning of schema export and import. Elle retourne les types de données personnalisés utilisés dans le schéma exporté ou importé.The method returns the custom data types used in the schema exported or imported. Un Collection<T> (le paramètre customDataTypes), qui est une collection de types, est passé à la méthode.The method is passed a Collection<T> (the customDataTypes parameter), which is a collection of types. La méthode doit ajouter des types connus supplémentaires à cette collection.The method should add additional known types to this collection. Les types de données personnalisés connus sont nécessaires pour activer la sérialisation et la désérialisation des données personnalisées à l’aide du DataContractSerializer.The known custom data types are needed to enable serialization and deserialization of custom data using the DataContractSerializer. Pour plus d’informations, consultez types connus de contrat de données.For more information, see Data Contract Known Types.

Implémentation d'un substitutImplementing a Surrogate

Pour utiliser le substitut de contrat de données dans WCF, vous devez suivre quelques procédures spéciales.To use the data contract surrogate within WCF, you must follow a few special procedures.

Pour utiliser un substitut pour la sérialisation et la désérialisationTo Use a Surrogate for Serialization and Deserialization

Utilisez le DataContractSerializer pour effectuer la sérialisation et la désérialisation des données avec le substitut.Use the DataContractSerializer to perform serialization and deserialization of data with the surrogate. Le DataContractSerializer est créé par le DataContractSerializerOperationBehavior.The DataContractSerializer is created by the DataContractSerializerOperationBehavior. Le substitut doit également être spécifié.The surrogate must also be specified.

Pour implémenter la sérialisation et la désérialisationTo implement serialization and deserialization
  1. Créez une instance du ServiceHost pour votre service.Create an instance of the ServiceHost for your service. Pour obtenir des instructions complètes, consultez programmation WCF de base.For complete instructions, see Basic WCF Programming.

  2. Pour chaque ServiceEndpoint de l'hôte de service spécifié, recherchez son OperationDescription.For every ServiceEndpoint of the specified service host, find its OperationDescription.

  3. Parcourez les comportements d'opération pour déterminer si une instance du DataContractSerializerOperationBehavior est détectée.Search through the operation behaviors to determine if an instance of the DataContractSerializerOperationBehavior is found.

  4. Si un DataContractSerializerOperationBehavior est détecté, affectez à sa propriété DataContractSurrogate une nouvelle instance du substitut.If a DataContractSerializerOperationBehavior is found, set its DataContractSurrogate property to a new instance of the surrogate. Si aucun DataContractSerializerOperationBehavior n'est détecté, créez une instance et affectez au membre DataContractSurrogate du nouveau comportement une nouvelle instance du substitut.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. Pour finir, ajoutez ce nouveau comportement aux comportements d'opérations actuels, comme illustré dans l'exemple suivant :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);
                }
            }
        }
    

Pour utiliser un substitut pour l'importation de métadonnéesTo Use a Surrogate for Metadata Import

Lors de l'importation de métadonnées telles que WSDL et XSD pour générer le code côté client, le substitut doit être ajouté au composant responsable de la génération du code à partir du schéma XSD, XsdDataContractImporter.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. Pour cela, modifiez directement le WsdlImporter utilisé pour importer les métadonnées.To do this, directly modify the WsdlImporter used to import metadata.

Pour implémenter un substitut pour l'importation de métadonnéesTo implement a surrogate for metadata importation
  1. Importez les métadonnées à l'aide de la classe WsdlImporter.Import the metadata using the WsdlImporter class.

  2. Utilisez la méthode TryGetValue pour vérifier si un XsdDataContractImporter a été défini.Use the TryGetValue method to check whether an XsdDataContractImporter has been defined.

  3. Si la méthode TryGetValue retourne la valeur false, créez un XsdDataContractImporter et affectez à sa propriété Options une nouvelle instance de la classe ImportOptions.If the TryGetValue method returns false, create a new XsdDataContractImporter and set its Options property to a new instance of the ImportOptions class. Autrement, utilisez l'importateur retourné par le paramètre out de la méthode TryGetValue.Otherwise, use the importer returned by the out parameter of the TryGetValue method.

  4. Si le XsdDataContractImporter n'a aucun ImportOptions défini, affectez à la propriété une nouvelle instance de la classe ImportOptions.If the XsdDataContractImporter has no ImportOptions defined, then set the property to be a new instance of the ImportOptions class.

  5. Affectez à la propriété DataContractSurrogate du ImportOptions du XsdDataContractImporter une nouvelle instance du substitut.Set the DataContractSurrogate property of the ImportOptions of the XsdDataContractImporter to a new instance of the surrogate.

  6. Ajoutez le XsdDataContractImporter à la collection retournée par la propriété State du WsdlImporter (héritée de la classe MetadataExporter.)Add the XsdDataContractImporter to the collection returned by the State property of the WsdlImporter (inherited from the MetadataExporter class.)

  7. Utilisez la méthode ImportAllContracts du WsdlImporter pour importer tous les contrats de données dans le schéma.Use the ImportAllContracts method of the WsdlImporter to import all of the data contracts within the schema. Durant la dernière étape, le code est généré à partir des schémas chargés en appelant le substitut.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;
    xsdInventoryImporter.Options ??= new ImportOptions();
    xsdInventoryImporter.Options.DataContractSurrogate = new InventorySurrogated();
    importer.State.Add(typeof(XsdDataContractImporter), xsdInventoryImporter);
    
    Collection<ContractDescription> contracts = importer.ImportAllContracts();
    

Pour utiliser un substitut pour l'exportation de métadonnéesTo Use a surrogate for Metadata Export

Par défaut, lors de l’exportation de métadonnées à partir de WCF pour un service, les schémas WSDL et XSD doivent être générés.By default, when exporting metadata from WCF for a service, both WSDL and XSD schema needs to be generated. Le substitut doit être ajouté au composant responsable de la génération du schéma XSD pour les types de contrat de données, XsdDataContractExporter.The surrogate needs to be added to the component responsible for generating XSD schema for data contract types, XsdDataContractExporter. Pour cela, utilisez un comportement qui implémente IWsdlExportExtension pour modifier le WsdlExporter ou modifiez directement le WsdlExporter utilisé pour exporter les métadonnées.To do this, either use a behavior that implements IWsdlExportExtension to modify the WsdlExporter, or directly modify the WsdlExporter used to export metadata.

Pour utiliser un substitut pour l'exportation de métadonnéesTo use a surrogate for metadata export
  1. Créez un WsdlExporter ou utilisez le paramètre wsdlExporter passé à la méthode ExportContract.Create a new WsdlExporter or use the wsdlExporter parameter passed to the ExportContract method.

  2. Utilisez la fonction TryGetValue pour vérifier si un XsdDataContractExporter a été défini.Use the TryGetValue function to check whether an XsdDataContractExporter has been defined.

  3. Si TryGetValue retourne la valeur false, créez un XsdDataContractExporter avec les schémas XML générés à partir du WsdlExporter et ajoutez-le à la collection retournée par la propriété State du WsdlExporter.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. Autrement, utilisez l'exportateur retourné par le paramètre out de la méthode TryGetValue.Otherwise, use the exporter returned by the out parameter of the TryGetValue method.

  4. Si le XsdDataContractExporter n'a aucun ExportOptions défini, affectez à la propriété Options une nouvelle instance de la classe ExportOptions.If the XsdDataContractExporter has no ExportOptions defined, then set the Options property to a new instance of the ExportOptions class.

  5. Affectez à la propriété DataContractSurrogate du ExportOptions du XsdDataContractExporter une nouvelle instance du substitut.Set the DataContractSurrogate property of the ExportOptions of the XsdDataContractExporter to a new instance of the surrogate. Les étapes suivantes d'exportation des métadonnées ne requièrent pas de modifications.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();
    

Voir aussiSee also