Suplentes de contratos de datosData Contract Surrogates

El suplente del contrato de datos es una característica avanzada que se basa en el modelo del contrato de datos.The data contract surrogate is an advanced feature built upon the Data Contract model. Esta característica está diseñada para ser utilizada para la personalización de tipo y substitución en situaciones donde los usuarios desean cambiar cómo un tipo se serializa, deserializa o se proyecta en metadatos.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. Algunos escenarios donde se puede utilizar un suplente es cuando un contrato de datos no se ha especificado para el tipo, los campos y las propiedades no están marcados con el atributo DataMemberAttribute o los usuarios desean crear dinámicamente las variaciones del esquema.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 serialización y deserialización se logran con el suplente del contrato de datos al utilizar DataContractSerializer para convertir de .NET Framework en un formato conveniente, como 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. El suplente del contrato de datos también se puede utilizar para modificar los metadatos exportados para los tipos, al generar representaciones de metadatos como documentos de esquema XML (XSD).Data contract surrogate can also be used to modify the metadata exported for types, when producing metadata representations such as XML Schema Documents (XSD). En la importación, el código se crea a partir de los metadatos y el suplente se puede utilizar en este caso también para personalizar el código generado.Upon import, code is created from metadata and the surrogate can be used in this case to customize the generated code as well.

Cómo funciona el suplenteHow the Surrogate Works

Un suplente funciona asignando un tipo (el tipo "original") a otro tipo (el tipo “suplente”).A surrogate works by mapping one type (the "original" type) to another type (the "surrogated" type). El ejemplo siguiente muestra el tipo original Inventory y un nuevo tipo suplente InventorySurrogated.The following example shows the original type Inventory and a new surrogate InventorySurrogated type. El tipo Inventory no se puede serializar pero el tipo InventorySurrogated es:The Inventory type is not serializable but the InventorySurrogated type is:

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

Dado que un contrato de datos no se ha definido para esta clase, convierta la clase en una clase de suplente con un contrato de datos.Because a data contract has not been defined for this class, convert the class to a surrogate class with a data contract. La clase de suplente se muestra en el ejemplo siguiente: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; }
    }
}

Implementar IDataContractSurrogateImplementing the IDataContractSurrogate

Para utilizar el suplente del contrato de datos, implemente la interfaz IDataContractSurrogate.To use the data contract surrogate, implement the IDataContractSurrogate interface.

A continuación, se muestra una información general de cada método de IDataContractSurrogate con una posible implementación.The following is an overview of each method of IDataContractSurrogate with a possible implementation.

GetDataContractTypeGetDataContractType

El método GetDataContractType asigna un tipo a otro.The GetDataContractType method maps one type to another. Este método se requiere para la serialización, deserialización, importación y exportación.This method is required for serialization, deserialization, import, and export.

La primera tarea está definiendo qué tipos se asignarán a otros tipos.The first task is defining what types will be mapped to other types. Por ejemplo:For example:

public Type GetDataContractType(Type type)
{
    Console.WriteLine("GetDataContractType");
    if (typeof(Inventory).IsAssignableFrom(type))
    {
        return typeof(InventorySurrogated);
    }
    return type;
}
  • Durante la serialización, la asignación devuelta por este método se utiliza subsiguientemente para transformar la instancia original en una instancia suplente llamando al método 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.

  • Durante la deserialización la asignación devuelta por este método es utilizada por el serializador para deserializar en una instancia del tipo suplente.On deserialization, the mapping returned by this method is used by the serializer to deserialize into an instance of the surrogate type. Llama subsiguientemente a GetDeserializedObject para transformar la instancia suplente en una instancia del tipo original.It subsequently calls GetDeserializedObject to transform the surrogated instance into an instance of the original type.

  • Durante la exportación, el tipo de suplente devuelto por este método se refleja para obtener el contrato de datos para utilizar para generar los metadatos.On export, the surrogate type returned by this method is reflected to get the data contract to use for generating metadata.

  • Durante la importación, el tipo inicial se cambia a un tipo suplente que se refleja para obtener el contrato de datos para utilizarlos para propósitos como referenciar el soporte.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.

El parámetro Type es el tipo del objeto que se serializa, deserializa, importa o exporta.The Type parameter is the type of the object that is being serialized, deserialized, imported, or exported. El método GetDataContractType debe devolver el tipo de entrada si el suplente no controla el tipo.The GetDataContractType method must return the input type if the surrogate does not handle the type. De lo contrario, devuelva el tipo suplente adecuado.Otherwise, return the appropriate surrogated type. Si existen varios tipos suplentes, las numerosas asignaciones se pueden definir en este método.If several surrogate types exist, numerous mappings can be defined in this method.

No se llama al método GetDataContractType para los tipos primitivos integrados del contrato de datos, como Int32 o String.The GetDataContractType method is not called for built-in data contract primitives, such as Int32 or String. Para otros tipos, como matrices, tipos definidos por el usuario y otras estructuras de datos, se llamará a este método para cada tipo.For other types, such as arrays, user-defined types, and other data structures, this method will be called for each type.

En el ejemplo anterior, el método comprueba si el parámetro type y Inventory son comparables.In the previous example, the method checks if the type parameter and Inventory are comparable. En tal caso, el método lo asigna a InventorySurrogated.If so, the method maps it to InventorySurrogated. Cuando se llama una serialización, deserialización, esquema de importación o esquema de exportación, se llama primero a esta función para determinar la asignación entre los tipos.Whenever a serialization, deserialization, import schema, or export schema is called, this function is called first to determine the mapping between types.

Método GetObjectToSerializeGetObjectToSerialize Method

El método GetObjectToSerialize convierte la instancia de tipo original en la instancia de tipo suplente.The GetObjectToSerialize method converts the original type instance to the surrogated type instance. El método se requiere para la serialización.The method is required for serialization.

El paso siguiente es definir la manera en que los datos físicos se asignarán de la instancia original a la instancia suplente implementando el método 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. Por ejemplo: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;
}

Se llama al método GetObjectToSerialize cuando se serializa un objeto.The GetObjectToSerialize method is called when an object is serialized. Este método transfiere los datos del tipo original a los campos del tipo suplente.This method transfers data from the original type to the fields of the surrogated type. Los campos pueden estar asignados directamente a campos suplentes o las manipulaciones de los datos originales pueden estar almacenadas en el suplente.Fields can be directly mapped to surrogate fields, or manipulations of the original data may be stored in the surrogate. Algunos posibles usos incluyen: asignar directamente los campos, realizar operaciones en los datos que se van a almacenar en los campos suplentes o almacenar el XML del tipo original en el campo suplente.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.

El parámetro targetType hace referencia al tipo declarado del miembro.The targetType parameter refers to the declared type of the member. Este parámetro es el tipo suplente devuelto por el método GetDataContractType.This parameter is the surrogated type returned by the GetDataContractType method. El serializador no exige que el objeto devuelto se pueda asignar a este tipo.The serializer does not enforce that the object returned is assignable to this type. El obj parámetro es el objeto que se va a serializar y se convertirá en su suplente si es necesario.The obj parameter is the object to serialize, and will be converted to its surrogate if necessary. Este método debe devolver el objeto de entrada si el suplente no controla el objeto.This method must return the input object if the surrogated does not handle the object. De lo contrario, se devolverá el nuevo objeto suplente.Otherwise, the new surrogate object will be returned. No se llama al suplente si el objeto es NULL.The surrogate is not called if the object is null. Las numerosas asignaciones del suplente para las diferentes instancias se pueden definir dentro de este método.Numerous surrogate mappings for different instances may be defined within this method.

Al crear DataContractSerializer, puede indicarle que conserve las referencias a objeto.When creating a DataContractSerializer, you can instruct it to preserve object references. (Para obtener más información, vea serialización y deserialización). Esto se hace estableciendo el parámetro preserveObjectReferences en su constructor en true.(For more information, see Serialization and Deserialization.) This is done by setting the preserveObjectReferences parameter in its constructor to true. En tal caso, se llama al suplente solo una vez para un objeto puesto que todas las serializaciones subsiguientes simplemente escriben la referencia en la secuencia.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 está establecido en false, se llama al suplente cada vez que se encuentra una instancia.If preserveObjectReferences is set to false, then the surrogate is called every time an instance is encountered.

Si el tipo de la instancia serializada difiere del tipo declarado, la información de tipo se escribe en la secuencia, por ejemplo, xsi:type para permitir deserializar la instancia en el otro extremo.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. Este proceso se produce tanto si el objeto es suplente como si no.This process occurs whether the object is surrogated or not.

El ejemplo anterior convierte los datos de la instancia Inventory en InventorySurrogated.The example above converts the data of the Inventory instance to that of InventorySurrogated. Comprueba el tipo del objeto y realiza las manipulaciones necesarias para convertirlo al tipo suplente.It checks the type of the object and performs the necessary manipulations to convert to the surrogated type. En este caso, los campos de la clase Inventory se copian directamente encima de los campos de la clase InventorySurrogated.In this case, the fields of the Inventory class are directly copied over to the InventorySurrogated class fields.

Método GetDeserializedObjectGetDeserializedObject Method

El método GetDeserializedObject convierte la instancia de tipo suplente en la instancia de tipo original.The GetDeserializedObject method converts the surrogated type instance to the original type instance. Se requiere para la deserialización.It is required for deserialization.

La tarea siguiente es definir la manera en que los datos físicos se asignarán de la instancia suplente a la instancia original.The next task is to define the way the physical data will be mapped from the surrogate instance to the original. Por ejemplo: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;
}

Se llama a este método solo durante la deserialización de un objeto.This method is called only during the deserialization of an object. Proporciona asignación inversa de datos para la deserialización del tipo suplente a su tipo original.It provides reverse data mapping for the deserialization from the surrogate type back to its original type. Similar al método GetObjectToSerialize, algunos posibles usos pueden ser intercambiar directamente los datos de campo, realizar las operaciones en los datos y almacenar los datos 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. Al deserializar, no siempre obtendrá los valores de datos exactos del original debido a las manipulaciones en la conversión de datos.When deserializing, you may not always obtain the exact data values from original due to manipulations in the data conversion.

El parámetro targetType hace referencia al tipo declarado del miembro.The targetType parameter refers to the declared type of the member. Este parámetro es el tipo suplente devuelto por el método GetDataContractType.This parameter is the surrogated type returned by the GetDataContractType method. El obj parámetro hace referencia al objeto que se ha deserializado.The obj parameter refers to the object that has been deserialized. El objeto se puede convertir de nuevo en su tipo original si es suplente.The object can be converted back to its original type if it is surrogated. Este método devuelve el objeto de entrada si el suplente no controla el objeto.This method returns the input object if the surrogate does not handle the object. De lo contrario, se devolverá el objeto deserializado una vez se haya completado su conversión.Otherwise, the deserialized object will be returned once its conversion has been completed. Si existen varios tipos de suplente, puede proporcionar la conversión de datos del suplente al tipo primario para cada uno indicando cada tipo y su conversión.If several surrogate types exist, you may provide data conversion from surrogate to primary type for each by indicating each type and its conversion.

Al devolver un objeto, las tablas de objeto internas se actualizan con el objeto devuelto por este suplente.When returning an object, the internal object tables are updated with the object returned by this surrogate. Cualquier referencia subsiguiente a una instancia obtendrá la instancia suplente de las tablas de objeto.Any subsequent references to an instance will obtain the surrogated instance from the object tables.

El ejemplo anterior vuelve a convertir objetos de tipo InventorySurrogated en el tipo Inventoryinicial.The previous example converts objects of type InventorySurrogated back to the initial type Inventory. En este caso, los datos se transfieren directamente desde InventorySurrogated a sus campos correspondiendo en Inventory.In this case, data is directly transferred back from InventorySurrogated to its corresponding fields in Inventory. Puesto que no hay manipulaciones de datos, el cada uno de los campos de miembro contendrá los mismos valores como antes de la serialización.Because there are no data manipulations, the each of the member fields will contain the same values as before the serialization.

Método GetCustomDataToExportGetCustomDataToExport Method

Al exportar un esquema, el método GetCustomDataToExport es opcional.When exporting a schema, the GetCustomDataToExport method is optional. Se utiliza para insertar datos adicionales o sugerencias en el esquema exportado.It is used to insert additional data or hints into the exported schema. Los datos adicionales se pueden insertar en el nivel de miembro o el nivel de tipo.Additional data can be inserted at the member level or type level. Por ejemplo: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";
    }
}

Este método (con dos sobrecargas) habilita la inclusión de información adicional en los metadatos en el nivel de miembro o en el nivel de tipo.This method (with two overloads) enables the inclusion of extra information into the metadata either at the member or type level. Es posible incluir sugerencias sobre si un miembro es público o privado, y comentarios que se conservarían a lo largo de la exportación e importación del esquema.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. Tal información se perdería sin este método.Such information would be lost without this method. Este método no provoca la inserción o eliminación de miembros o tipos, sino que agrega datos adicionales a los esquemas en cualquiera de estos niveles.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.

El método está sobrecargado y puede tomar Type (parámetro clrtype) o MemberInfo (parámetro memberInfo).The method is overloaded and can take either a Type (clrtype parameter) or MemberInfo (memberInfo parameter). El segundo parámetro es siempre Type (parámetro dataContractType).The second parameter is always a Type (dataContractType parameter). Se llama a este método para cada miembro y tipo del tipo suplente dataContractType.This method is called for every member and type of the surrogated dataContractType type.

Cualquiera de estas sobrecargas debe devolver null o un objeto serializable.Either of these overloads must return either null or a serializable object. Un objeto no NULL se serializará como anotación en el esquema exportado.A non-null object will be serialized as annotation into the exported schema. Para la sobrecarga Type, cada tipo que se exporta al esquema se envía a este método en el primer parámetro junto con el tipo suplente como el parámetro 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. Para la sobrecarga MemberInfo, cada miembro que se exporta al esquema envía su información como el parámetro memberInfo con el tipo suplente en el segundo parámetro.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étodo GetCustomDataToExport (Tipo, Tipo)GetCustomDataToExport Method (Type, Type)

Se llama al método IDataContractSurrogate.GetCustomDataToExport(Type, Type) durante la exportación de esquema para cada definición de tipo.The IDataContractSurrogate.GetCustomDataToExport(Type, Type) method is called during schema export for every type definition. El método agrega información a los tipos dentro del esquema al exportar.The method adds information to the types within the schema when exporting. Cada tipo definido se envía a este método para determinar si hay datos adicionales que deban incluirse en el esquema.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étodo GetCustomDataToExport (MemberInfo, Tipo)GetCustomDataToExport Method (MemberInfo, Type)

Se llama a IDataContractSurrogate.GetCustomDataToExport(MemberInfo, Type) durante la exportación para cada miembro en los tipos que se exportan.The IDataContractSurrogate.GetCustomDataToExport(MemberInfo, Type) is called during export for every member in the types that are exported. Esta función le permite personalizar cualquier comentario para los miembros que se incluirán en el esquema durante la exportación.This function enables you to customize any comments for the members that will be included in the schema upon export. La información para cada miembro dentro de la clase se envía a este método para comprobar si deben agregarse datos adicionales en el esquema.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.

El ejemplo anterior realiza búsquedas a través de dataContractType para cada miembro del suplente.The example above searches through the dataContractType for each member of the surrogate. Después devuelve el modificador de acceso adecuado para cada campo.It then returns the appropriate access modifier for each field. Sin esta personalización, el valor predeterminado para los modificadores de acceso es público.Without this customization, the default value for access modifiers is public. Por consiguiente, todos los miembros se definirían como públicos en el código generado utilizando el esquema exportado sin importar cuáles sean sus restricciones de acceso.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 no se utilizara esta implementación, el miembro numpens sería público en el esquema exportado aunque se hubiera definido en el suplente como privado.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. A través del uso de este método, en el esquema exportado, el modificador de acceso se puede generar como privado.Through the use of this method, in the exported schema, the access modifier can be generated as private.

Método GetReferencedTypeOnImportGetReferencedTypeOnImport Method

Este método asigna Type del suplente al tipo original.This method maps the Type of the surrogate to the original type. Este método es opcional para la importación del esquema.This method is optional for schema importation.

Al crear un suplente que importa un esquema y genera el código para él, la tarea siguiente es definir el tipo de una instancia suplente en relación a su tipo original.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 el código generado necesita hacer referencia a un tipo de usuario existente, esto se hace implementando el método GetReferencedTypeOnImport.If the generated code needs to reference an existing user type, this is done by implementing the GetReferencedTypeOnImport method.

Al importar un esquema, se llama a este método para cada declaración de tipos para asignar el contrato de datos suplente a un tipo.When importing a schema, this method is called for every type declaration to map the surrogated data contract to a type. Los parámetros de cadena typeName y typeNamespace definen el nombre y espacio de nombres del tipo suplente.The string parameters typeName and typeNamespace define the name and namespace of the surrogated type. El valor devuelto para GetReferencedTypeOnImport se utiliza para determinar si debe generarse un nuevo tipo.The return value for GetReferencedTypeOnImport is used to determine whether a new type needs to be generated. Este método debe devolver un tipo válido o NULL.This method must return either a valid type or null. Para los tipos válidos, el tipo devuelto se utilizará como un tipo referenciado en el código generado.For valid types, the type returned will be used as a referenced type in the generated code. Si se devuelve NULL, no se referenciará ningún tipo y deberá crearse un nuevo tipo.If null is returned, no type will be referenced and a new type must be created. Si existen varios suplentes, es posible volver a realizar la asignación para cada tipo suplente a su tipo inicial.If several surrogates exist, it is possible to perform the mapping for each surrogate type back to its initial type.

El parámetro customData es originalmente el objeto devuelto de GetCustomDataToExport.The customData parameter is the object originally returned from GetCustomDataToExport. Se utiliza customData cuando los autores suplentes desean insertar datos adicionales/sugerencias en los metadatos para utilizar durante importación para generar código.This customData is used when surrogate authors want to insert extra data/hints into the metadata to use during import to generate code.

Método ProcessImportedTypeProcessImportedType Method

El método ProcessImportedType personaliza cualquier tipo creado a partir de la importación del esquema.The ProcessImportedType method customizes any type created from schema importation. Este método es opcional.This method is optional.

Al importar un esquema, este método permite la personalización de cualquiera tipo importado e información de compilación.When importing a schema, this method allows for any imported type and compilation information to be customized. Por ejemplo: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;
}

Durante la importación, se llama a este método para cada tipo generado.During import, this method is called for every type generated. Cambie el CodeTypeDeclaration especificado o modifique CodeCompileUnit.Change the specified CodeTypeDeclaration or modify the CodeCompileUnit. Esto incluye cambiar el nombre, miembros, atributos y muchas otras propiedades de CodeTypeDeclaration.This includes changing the name, members, attributes, and many other properties of the CodeTypeDeclaration. Al procesar CodeCompileUnit, es posible modificar las directivas, espacios de nombres, ensamblados referenciados y varios otros aspectos.By processing the CodeCompileUnit, it is possible to modify the directives, namespaces, referenced assemblies, and several other aspects.

El parámetro CodeTypeDeclaration contiene la declaración de tipos de código DOM.The CodeTypeDeclaration parameter contains the code DOM type declaration. El parámetro CodeCompileUnit permite la modificación para procesar el código.The CodeCompileUnit parameter allows for modification for processing the code. Devolver los resultados null descartados en la declaración de tipos.Returning null results in the type declaration being discarded. A la inversa, al devolver CodeTypeDeclaration, se conservan las modificaciones.Conversely, when returning a CodeTypeDeclaration, the modifications are preserved.

Si se insertan datos personalizados durante la exportación de metadatos, debe ser proporcionado al usuario durante la importación para que lo pueda utilizar.If custom data is inserted during metadata export, it needs to be provided to the user during import so that it can be used. Estos datos personalizados se pueden utilizar para las sugerencias del modelo de programación u otros comentarios.This custom data can be used for programming model hints, or other comments. Cada instancia CodeTypeDeclaration y CodeTypeMember incluye datos personalizados como la propiedad UserData, convertida al tipo IDataContractSurrogate.Each CodeTypeDeclaration and CodeTypeMember instance includes custom data as the UserData property, cast to the IDataContractSurrogate type.

El ejemplo anterior realiza algunos cambios en el esquema importado.The example above performs some changes on the schema imported. El código conserva los miembros privados del tipo original utilizando un suplente.The code preserves private members of the original type by using a surrogate. El modificador de acceso predeterminado al importar un esquema es public.The default access modifier when importing a schema is public. Por consiguiente, todos los miembros del esquema suplente serán públicos a menos que se hayan modificado, como en este ejemplo.Therefore, all members of the surrogate schema will be public unless modified, as in this example. Durante la exportación, los datos personalizados se insertan en los metadatos sobre qué miembros son privados.During export, custom data is inserted into the metadata about which members are private. El ejemplo consulta los datos personalizados, comprueba si el modificador de acceso es privado y, a continuación, modifica el miembro adecuado para que sea privado estableciendo sus atributos.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. Sin esta personalización, el miembro numpens se definiría como público en lugar de privado.Without this customization, the numpens member would be defined as public instead of private.

Método GetKnownCustomDataTypesGetKnownCustomDataTypes Method

Este método obtiene tipos de datos personalizados definidos a partir del esquema.This method obtains custom data types defined from the schema. Este método es opcional para la importación del esquema.The method is optional for schema importation.

Se llama al método al principio de la exportación e importación del esquema.The method is called at the beginning of schema export and import. El método devuelve los tipos de datos personalizados utilizados en el esquema exportado o importado.The method returns the custom data types used in the schema exported or imported. El método se pasa a Collection<T> (el parámetro customDataTypes), que es una colección de tipos.The method is passed a Collection<T> (the customDataTypes parameter), which is a collection of types. El método debería agregar los tipos conocidos adicionales a esta colección.The method should add additional known types to this collection. Los tipos de datos personalizados conocidos son necesarios para habilitar la serialización y deserialización de datos personalizados utilizando DataContractSerializer.The known custom data types are needed to enable serialization and deserialization of custom data using the DataContractSerializer. Para obtener más información, vea tipos conocidos de contratos de datos.For more information, see Data Contract Known Types.

Implementar un suplenteImplementing a Surrogate

Para utilizar el suplente del contrato de datos en WCF, debe seguir algunos procedimientos especiales.To use the data contract surrogate within WCF, you must follow a few special procedures.

Para utilizar un suplente para la serialización y deserializaciónTo Use a Surrogate for Serialization and Deserialization

Utilice DataContractSerializer para realizar la serialización y deserialización de datos con el suplente.Use the DataContractSerializer to perform serialization and deserialization of data with the surrogate. DataContractSerializer es creado por DataContractSerializerOperationBehavior.The DataContractSerializer is created by the DataContractSerializerOperationBehavior. También se debe especificar el suplente.The surrogate must also be specified.

Para implementar serialización y deserializaciónTo implement serialization and deserialization
  1. Cree una instancia de ServiceHost para su servicio.Create an instance of the ServiceHost for your service. Para obtener instrucciones completas, vea programación básica de WCF.For complete instructions, see Basic WCF Programming.

  2. Para cada ServiceEndpoint del host del servicio especificado, busque OperationDescription.For every ServiceEndpoint of the specified service host, find its OperationDescription.

  3. Busque a través de los comportamientos de la operación para determinar si se encuentra una instancia de DataContractSerializerOperationBehavior.Search through the operation behaviors to determine if an instance of the DataContractSerializerOperationBehavior is found.

  4. Si se encuentra DataContractSerializerOperationBehavior, establezca su propiedad DataContractSurrogate en una nueva instancia del suplente.If a DataContractSerializerOperationBehavior is found, set its DataContractSurrogate property to a new instance of the surrogate. Si no se encuentra DataContractSerializerOperationBehavior, cree una nueva instancia y establezca el miembro DataContractSurrogate del nuevo comportamiento en una nueva instancia del suplente.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. Finalmente, agregue este nuevo comportamiento a los comportamientos actuales de la operación, como se muestra en el ejemplo siguiente: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);
                }
            }
        }
    

Para utilizar un suplente para importar metadatosTo Use a Surrogate for Metadata Import

Al importar los metadatos como WSDL y XSD para generar el código del lado del cliente, el suplente debe ser agregado al componente responsable para generar código del esquema 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. Para ello, directamente modifique WsdlImporter utilizado para importar los metadatos.To do this, directly modify the WsdlImporter used to import metadata.

Para implementar un suplente para la importación de metadatosTo implement a surrogate for metadata importation
  1. Importe los metadatos mediante la clase WsdlImporter.Import the metadata using the WsdlImporter class.

  2. Utilice el método TryGetValue para comprobar si se ha definido XsdDataContractImporter.Use the TryGetValue method to check whether an XsdDataContractImporter has been defined.

  3. Si el método TryGetValue devuelve false, cree un nuevo XsdDataContractImporter y establece su propiedad Options a una nueva instancia de la clase ImportOptions.If the TryGetValue method returns false, create a new XsdDataContractImporter and set its Options property to a new instance of the ImportOptions class. De lo contrario, utilice el importador devuelto por el parámetro out del método TryGetValue.Otherwise, use the importer returned by the out parameter of the TryGetValue method.

  4. Si XsdDataContractImporter no tiene ImportOptions definido, establezca la propiedad para que sea una nueva instancia de la clase ImportOptions.If the XsdDataContractImporter has no ImportOptions defined, then set the property to be a new instance of the ImportOptions class.

  5. Establezca la propiedad DataContractSurrogate de ImportOptions de XsdDataContractImporter en una nueva instancia del suplente.Set the DataContractSurrogate property of the ImportOptions of the XsdDataContractImporter to a new instance of the surrogate.

  6. Agregue XsdDataContractImporter a la colección devuelta por la propiedad State de WsdlImporter (heredada de la clase MetadataExporter).Add the XsdDataContractImporter to the collection returned by the State property of the WsdlImporter (inherited from the MetadataExporter class.)

  7. Utilice el método ImportAllContracts de WsdlImporter para importar todos los contratos de datos dentro del esquema.Use the ImportAllContracts method of the WsdlImporter to import all of the data contracts within the schema. Durante el último paso, el código se genera a partir de los esquemas cargados llamando en el suplente.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();
    

Para utilizar un suplente para exportar metadatosTo Use a surrogate for Metadata Export

De forma predeterminada, cuando se exportan metadatos de WCF para un servicio, es necesario generar el esquema de WSDL y XSD.By default, when exporting metadata from WCF for a service, both WSDL and XSD schema needs to be generated. El suplente necesita ser agregado al componente responsable para generar el esquema XSD para los tipos de contrato de datos, XsdDataContractExporter.The surrogate needs to be added to the component responsible for generating XSD schema for data contract types, XsdDataContractExporter. Para ello, utilice un comportamiento que implemente IWsdlExportExtension para modificar WsdlExportero directamente modifique WsdlExporter utilizado para exportar los metadatos.To do this, either use a behavior that implements IWsdlExportExtension to modify the WsdlExporter, or directly modify the WsdlExporter used to export metadata.

Para utilizar un suplente para exportar metadatosTo use a surrogate for metadata export
  1. Cree un nuevo WsdlExporter o utilice el parámetro wsdlExporter pasado al método ExportContract.Create a new WsdlExporter or use the wsdlExporter parameter passed to the ExportContract method.

  2. Utilice la función TryGetValue para comprobar si se ha definido XsdDataContractExporter.Use the TryGetValue function to check whether an XsdDataContractExporter has been defined.

  3. Si TryGetValue devuelve false, cree un nuevo XsdDataContractExporter con los esquemas XML generados de WsdlExportery agréguelo a la colección devuelta por la propiedad State de 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. De lo contrario, utilice el exportador devuelto por el parámetro out del método TryGetValue.Otherwise, use the exporter returned by the out parameter of the TryGetValue method.

  4. Si XsdDataContractExporter no tiene ExportOptions definido, establezca la propiedad Options en una nueva instancia de la clase ExportOptions.If the XsdDataContractExporter has no ExportOptions defined, then set the Options property to a new instance of the ExportOptions class.

  5. Establezca la propiedad DataContractSurrogate de ExportOptions de XsdDataContractExporter en una nueva instancia del suplente.Set the DataContractSurrogate property of the ExportOptions of the XsdDataContractExporter to a new instance of the surrogate. Los pasos subsiguientes para exportar los metadatos no requieren ningún cambio.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();
    

Vea tambiénSee also