Compartir a través de


Importación del esquema para generar clases

Para generar las clases desde los esquemas que se pueden utilizar con Windows Communication Foundation (WCF), utilice la clase XsdDataContractImporter. En este tema se describen el proceso y variaciones.

El proceso de importación

El proceso de importación del esquema se inicia con XmlSchemaSet y genera CodeCompileUnit.

XmlSchemaSet forma parte del Modelo de objetos de esquemas (SOM) de .NET Framework que representa un conjunto de documentos de esquema (XSD) de lenguaje de definición de esquemas XML. Para crear un objeto XmlSchemaSet a partir de un conjunto de documentos XSD, deserialice cada documento en un objeto (utilizar XmlSerializer) XmlSchema y agregue estos objetos a un nuevo XmlSchemaSet.

CodeCompileUnit forma parte del Modelo de objetos de documento (CodeDOM) de Código de .NET Framework que representa el código .NET Framework de una manera abstracta. Para generar el código real a partir de CodeCompileUnit, utilice una subclase de la clase CodeDomProvider, como CSharpCodeProvider o la clase VBCodeProvider.

Importar un esquema

  1. Cree una instancia de XsdDataContractImporter.

  2. Opcional. Pase CodeCompileUnit en el constructor. Los tipos generados durante la importación del esquema se agregan a la instancia CodeCompileUnit en lugar de iniciarse con un CodeCompileUniten blanco.

  3. Opcional. Llame a uno de los métodos CanImport. El método determina si el esquema determinado es un esquema de contrato de datos válido y si se puede importar. El método CanImport tiene las mismas sobrecargas que Import (el paso siguiente).

  4. Llame a uno de los métodos Import sobrecargados, por ejemplo, el método Import.

    La sobrecarga más simple toma XmlSchemaSet e importa todos los tipos, incluidos los tipos anónimos, situados en ese esquema establecido. Otras sobrecargas le permiten especificar el tipo XSD o una lista de tipos a importar (en el formulario de XmlQualifiedName o una colección de los objetos XmlQualifiedName ). En este caso, sólo se importan los tipos especificados. Una sobrecarga toma XmlSchemaElement que importa un elemento determinado fuera de XmlSchemaSet, así como su tipo asociado (si es anónimo o no). Esta sobrecarga devuelve XmlQualifiedName, que representa el nombre de contrato de datos del tipo generado para este elemento.

    Varias llamadas del método Import producen como resultado varios elementos que se agregan al mismo CodeCompileUnit. Un tipo no se genera en CodeCompileUnit si ya existe en este. Llame varias veces Import al mismo XsdDataContractImporter en lugar de utilizar varios objetos XsdDataContractImporter. Ésta es la manera recomendada de evitar que se generen tipos duplicados.

    Nota

    Si se produce un error durante la importación, CodeCompileUnit estará en un estado imprevisible. Si utiliza CodeCompileUnit como resultado de una importación en la que se ha producido un error, podría exponerse a vulnerabilidades de seguridad.

  5. Obtenga acceso a CodeCompileUnit a través de la propiedad CodeCompileUnit.

Importar opciones: Personalizar los tipos generados

Puede establecer la propiedad Options de XsdDataContractImporter a una instancia de la clase ImportOptions para administrar varios aspectos del proceso de importación. Hay varias opciones influyen directamente en los tipos generados.

Controlar el nivel de acceso (GenerateInternal o el modificador /interno)

Esto corresponde al modificador /interno de ServiceModel Metadata Utility Tool (Svcutil.exe).

Normalmente, los tipos públicos se generan a partir del esquema, con campos privados y propiedades de miembro de datos públicos coincidentes. Para generar tipos internos en su lugar, establezca la propiedad GenerateInternal en true.

El ejemplo siguiente muestra un esquema transformado en una clase interna cuando la propiedad GenerateInternal está establecida en true.

Controlar espacios de nombres (Espacios de nombres o el modificador /espacio de nombres)

Esto corresponde al modificador /espacio de nombres de la herramienta Svcutil.exe.

Normalmente, los tipos generados a partir del esquema se generan en los espacios de nombres .NET Framework, con cada espacio de nombres XSD que corresponde a un espacio de nombres .NET Framework determinado según una asignación descrita en Referencia de esquema de contrato de datos. Puede personalizar esta asignación mediante la propiedad Namespaces a Dictionary. Si se encuentra un espacio de nombres XSD determinado en el diccionario, el espacio de nombres .NET Framework correspondiente también se toma de su diccionario.

Por ejemplo, considere el siguiente esquema:

El ejemplo siguiente utiliza la propiedad Namespaces para asignar el espacio de nombres "http://schemas.contoso.com/carSchema" a "Contoso.Cars."

Agregar SerializableAttribute (GenerateSerializable o el modificador /serializable)

Esto corresponde al modificador /serializable en la herramienta Svcutil.exe.

En algunas ocasiones, es importante que los tipos generados a partir del esquema se puedan utilizar con los motores de la serialización en tiempo de ejecución .NET Framework (por ejemplo, BinaryFormatter y las clases SoapFormatter ). Esto es útil cuando se utilizan los tipos para la comunicación remota .NET Framework. Para habilitarlo, debe aplicar el atributo SerializableAttribute a los tipos generados además del atributo DataContractAttribute normal. Se genera el atributo automáticamente si la opción de importación GenerateSerializable está establecida en true.

El ejemplo siguiente muestra la clase Vehicle generada con la opción establecida de importación GenerateSerializable a true.

Agregar compatibilidad de enlace de datos (EnableDataBinding o el modificador /enableDataBinding)

Esto corresponde al modificador /enableDataBinding en la herramienta Svcutil.exe.

Es posible que quiera enlazar los tipos generados a partir del esquema a los componentes de interfaz gráfica de usuario para que las actualizaciones en las instancias de estos tipos se actualicen automáticamente en la Interfaz de usuario. XsdDataContractImporter puede generar tipos que implementan la interfaz INotifyPropertyChanged de manera que cualquier cambio de propiedad active un evento. Si está generando tipos para utilizarlos con un entorno de programación de Interfaz de usuario de cliente que admite esta interfaz (como Windows Presentation Foundation (WPF)), establezca la propiedad EnableDataBinding en true para habilitar esta característica.

El ejemplo siguiente muestra la clase Vehicle generada con EnableDataBinding establecida a true.

Opciones de importación: Elegir tipos de colección

Dos modelos especiales en XML representan colecciones de elementos: listas de elementos y asociaciones entre un elemento y otro. A continuación se muestra un ejemplo de una lista de cadenas:

A continuación, se muestra un ejemplo de una asociación entre una cadena y un entero (city name y population).

Nota

Las asociaciones también se podrían considerar una lista. Por ejemplo, puede ver la asociación anterior como una lista de objetos city complejos que tienen dos campos (un campo de cadena y un campo de valor entero). Ambos modelos tienen una representación en el Esquema XSD. No hay ningún modo de diferenciar entre una lista y una asociación, así que estos modelos siempre se tratan como listas a menos que haya una anotación especial en el esquema específica para WCF. La anotación indica que un modelo determinado representa una asociación. Para obtener más información, consulte Referencia de esquema de contrato de datos.

Normalmente, una lista se importa como un contrato de datos de colección derivado de una Lista Genérica o como una matriz .NET Framework, según si el esquema sigue el modelo estándar de denominación o no para las colecciones. Puede obtener más información en Tipos de colección en contratos de datos. Las asociaciones se importan normalmente como Dictionary o como un contrato de datos de colección derivado del objeto de diccionario. Por ejemplo, considere el siguiente esquema:

Esto se importaría como se indica a continuación (se muestran los campos en lugar de las propiedades para facilitar la lectura).

Se pueden personalizar los tipos de colección generados para estos modelos del esquema. Por ejemplo, puede querer generar colecciones derivadas de BindingList en lugar de la clase List para enlazar el tipo a un cuadro de lista y para que se actualice automáticamente cuando cambien los contenidos de la colección. Para ello, establezca la propiedad ReferencedCollectionTypes de la clase ImportOptions en una lista de tipos de colección que se utilizarán (de ahora en adelante conocidos como los tipos con referencia). Cuando se importa una colección, se digitaliza esta lista de tipos de colección con referencia y, si se encuentra uno, se utiliza la colección que mejor coincida. Solamente se comparan asociaciones con tipos que implementan la interfaz genérica o no genérica IDictionary, mientras que las listas se comparan con cualquier tipo de colección compatible.

Por ejemplo, si la propiedad ReferencedCollectionTypes está establecida en BindingList, el tipo people en el ejemplo anterior se genera como se indica a continuación.

Se considera que un tipo genérico cerrado es el que más coincide. Por ejemplo, si los tipos BindingList(Of Integer) y ArrayList se pasan a la colección de tipos con referencia, las listas de enteros encontradas en el esquema se importan como BindingList(Of Integer). Cualquier otra lista, por ejemplo, List(Of String), se importa como ArrayList.

Si un tipo que implementa la interfaz IDictionary genérica se agrega a la colección de tipos con referencia, sus parámetros de tipo deben estar o totalmente abiertos o totalmente cerrados.

No se permiten duplicados. Por ejemplo, no puede agregar List(Of Integer) sino Collection(Of Integer) a los tipos con referencia. Eso haría imposible determinar cuál se debería utilizar cuando una lista de enteros se encuentra en esquema. Los duplicados se detectarán sólo si hay un tipo en esquema que expone el problema de los duplicados. Por ejemplo, si el esquema importado no contiene listas de enteros, puede tener List(Of Integer) y Collection(Of Integer) en la colección de tipos con referencia, pero no tendrán ningún efecto.

El mecanismo de tipos de colección con referencia funciona igual de bien para las colecciones de tipos complejos (incluso las colecciones de otras colecciones) y no sólo para las colecciones de primitivos.

La propiedad ReferencedCollectionTypes corresponde al modificador /collectionType en la herramienta SvcUtil.exe. Tenga en cuenta que para hacer referencia a varios tipos de colección, se debe especificar varias veces el modificador /collectionType Si el tipo no está en MsCorLib.dll, se debe hacer referencia también a su ensamblado mediante el modificador /referencia.

Opciones de importación: Hacer referencia a tipos existentes

De vez en cuando, los tipos en esquema corresponden a los tipos .NET Framework existentes y no es necesario generar estos tipos desde el principio. (Esta sección sólo se aplica a los tipos noncollection. Para los tipos de colección, consulte la sección anterior.)

Por ejemplo, puede tener un tipo de contrato de datos "Persona" estándar para toda la compañía que siempre quiere utilizar cuando represente una persona. Cuando algún servicio utiliza este tipo y su esquema aparece en los metadatos del servicio, puede reutilizar el tipo Person existente cuando importe este esquema en lugar de generar uno nuevo para cada servicio.

Para ello, pase una lista de tipos .NET Framework que quiere reutilizar en la colección que la propiedad ReferencedTypes devuelve en la clase ImportOptions. Si alguno de estos tipos tiene un nombre de contrato de datos y espacio de nombres que coincide con el nombre y espacio de nombres de un tipo de esquema, se realiza una comparación estructural. Si se determina que los tipos coinciden en nombres y en estructuras, el tipo .NET Framework existente se reutiliza en lugar de generar uno nuevo. Si sólo coincide el nombre y no la estructura, se produce una excepción. Tenga en cuenta que no hay ninguna concesión para controlar las versiones al hacer referencia a tipos (por ejemplo, agregar nuevos miembros de datos opcionales). Las estructuras deben coincidir con exactitud.

Es legal agregar varios tipos con el mismo nombre de contrato de datos y espacio de nombres a la colección de tipos con referencia, siempre que no se importe ningún tipo de esquema con ese nombre y espacio de nombres. Esto le permite agregar con facilidad todos los tipos en un ensamblado a la colección sin preocuparse por los duplicados para los tipos que realmente no se producen en esquema.

La propiedad ReferencedTypes corresponde al modificador /referencia en ciertos modos de operación de la herramienta Svcutil.exe.

Nota

Cuando se utiliza Svcutil.exe o (en Visual Studio) las herramientas Agregar referencia de servicio, se hace referencia a todos los tipos en MsCorLib.dll automáticamente.

Opciones de importación: Importar esquema Non-DataContract como tipos IXmlSerializable

XsdDataContractImporter admite un subconjunto limitado del esquema. Si las construcciones de esquema no compatibles están presentes (por ejemplo, atributos XML), se produce un error en los intentos de importación y se genera una excepción. Sin embargo, si se establece la propiedad ImportXmlType en true, se extiende el intervalo de esquema compatible. Cuando se establece en true, XsdDataContractImporter genera tipos que implementan la interfaz IXmlSerializable. Esto permite el acceso directo a la representación XML de estos tipos.

Consideraciones de diseño

  • Puede ser difícil trabajar directamente con la representación XML con tipos débiles. Considere utilizar un motor de serialización alternativo, como por ejemplo XmlSerializer, para trabajar con esquema no compatible con contratos de datos con establecimiento inflexible de tipos. Para obtener más información, consulte Utilización de la clase XmlSerializer.
  • XsdDataContractImporter no puede importar algunas construcciones de esquema incluso cuando la propiedad ImportXmlType está establecida en true. De nuevo, considere utilizar XmlSerializer para estos casos.
  • Las construcciones exactas de esquema admitidas cuando ImportXmlType es true o false se describen en Referencia de esquema de contrato de datos.
  • El esquema para tipos IXmlSerializable generados que no retienen la fidelidad cuando se importan y exportan. Es decir, exportar el esquema a partir de los tipos generados e importar como clases no devuelve el esquema original.

Es posible combinar la opción ImportXmlType con la opción ReferencedTypes descrita previamente. Para los tipos que tienen que ser generados como implementaciones IXmlSerializable, se omite la comprobación estructural cuando se utiliza la característica ReferencedTypes.

La opción ImportXmlType corresponde al modificador /importXmlTypes de la herramienta Svcutil.exe.

Trabajar con tipos generados IXmlSerializable

Los tipos IXmlSerializable generados contienen un campo privado, denominado "nodesField", que devuelve una matriz de los objetos XmlNode. Cuando se deserializa una instancia de este tipo, usted puede tener acceso directamente a los datos XML a través de este campo utilizando el Modelo de objetos del documento XML. Cuando se serializa una instancia de este tipo, usted puede establecer este campo a los datos XML deseados y se serializará.

Esto se logra a través de la implementación IXmlSerializable. En el tipo IXmlSerializable generado, la implementación ReadXml llama al método ReadNodes de la clase XmlSerializableServices. El método es un método auxiliar que convierte XML proporcionado a través de XmlReader a una matriz de los objetos XmlNode. La implementación WriteXml hace el contrario y convierte la matriz de los objetos XmlNode a una secuencia de llamadas XmlWriter. Esto se realiza mediante el método WriteNodes.

Se puede ejecutar el proceso de exportación del esquema en las clases IXmlSerializable generadas. Como se ha expresado previamente, no se le devolverá el esquema original. En su lugar, obtendrá el tipo XSD estándar “anyType”, que es un carácter comodín para cualquier tipo XSD.

Esto se logra aplicando el atributo XmlSchemaProviderAttribute a las clases IXmlSerializable generadas y especificando un método que llama al método AddDefaultSchema para generar el tipo "anyType."

Nota

El tipo XmlSerializableServices existe solamente para admitir esta característica determinada. No se recomienda utilizarlo para cualquier otro propósito.

Opciones de importación: Opciones avanzadas

Estas son opciones de importación avanzadas:

  • Propiedad CodeProvider. Especifique CodeDomProvider que quiere utilizar para generar el código para las clases generadas. El mecanismo de importación intenta evitar características que CodeDomProvider no admite. Por ejemplo, el lenguaje J# no admite genéricos. Si especifica el proveedor de código de J# en esta propiedad, ningún tipo genérico se genera en CodeCompileUnit del importador. Si no se establece CodeProvider, el conjunto completo de características .NET Framework se utiliza sin las restricciones.
  • Propiedad DataContractSurrogate. Se puede especificar una implementación IDataContractSurrogate con esta propiedad. IDataContractSurrogate personaliza el proceso de importación. Para obtener más información, consulte Suplentes de contratos de datos. De forma predeterminada, no se utiliza ningún suplente.

Consulte también

Referencia

DataContractSerializer
XsdDataContractImporter
XsdDataContractExporter
ImportOptions

Conceptos

Referencia de esquema de contrato de datos
Suplentes de contratos de datos
Importación y exportación de esquemas
Exportación de esquemas desde las clases
Referencia de esquema de contrato de datos