2009-12-23 16 views
11

Usando DataContractSerializer para serializar mi objeto consigo una salida similar a¿Hay alguna manera de hacer que DataContractSerializer produzca XML más limpio?

<?xml version="1.0" encoding="utf-8" ?> 
<AgentNotification xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/The.name.space.Notifications"> 
    <_x003C_Created_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" /> 
    <_x003C_Id_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" />   
<_x003C_Email_x003E_k__BackingField>[email protected]</_x003C_Email_x003E_k__BackingField> 
    <_x003C_Name_x003E_k__BackingField>Random Person</_x003C_Name_x003E_k__BackingField> 
<_x003C_Policies_x003E_k__BackingField> 
<PolicyNotification> 
    <_x003C_Created_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" /> 
    <_x003C_Id_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" /> 
    <_x003C_ConfirmationNumber_x003E_k__BackingField>Some number</_x003C_ConfirmationNumber_x003E_k__BackingField> 
    </PolicyNotification> 
<PolicyNotification> 
    </_x003C_Policies_x003E_k__BackingField> 
    </AgentNotification> 

¿Hay manera alguna para que las etiquetas de salida que son simplemente

<Id> 
<Name> 

etc, sin la necesidad de cubrir mis clases con atributos?

Si no hay una manera en que la salida de esto garantice ser la misma siempre correcta? ¿De modo que si uso esto para renderizar mis gráficos de objetos son XML para combinar con un documento X * para la generación de archivos que nunca me toparé con un problema donde mis nodos cambian de nombre y el documento sale en blanco?

+3

No. Y deja de preocuparte por cómo se ve tu xml. Solo lleva al desamor. – Will

+0

Debe hacer que una respuesta lo haga. –

Respuesta

8

Esto sucede porque debe haber marcado sus tipos (por ejemplo, AgentNotification) con [Serializable]. Cuando DataContractSerializer encuentra un tipo marcado con [Serializable] pero no explícitamente [DataContract], genera un default contract para el tipo que coincide con la forma en que BinaryFormatter serializa una clase, que debe serializar all member variables of a class — even variables marked as private - por nombre.Para auto-implemented properties, esto significa que el secret backing fields se serializa por su nombre; sus nombres son los nombres de elementos peculiares que está viendo.

La manera más fácil de resolver esto es eliminar el atributo [Serializable] de sus clases. Es casi seguro que no lo necesita a menos que realmente esté usando BinaryFormatter o SoapFormatter. Una vez hecho esto, DataContractSerializer ahora serializará sus propiedades públicas y campos por nombre, en lugar de campos públicos y privados por nombre.

+0

Eso probablemente hubiera sido lo que quería hace 6 años. Pero en algún momento simplemente dejé de usar XSLT y comencé a usar Postal + RazorViewEngine para generar contenido de correo electrónico. –

1

El DataContractSerializer serializará todas las propiedades públicas (si no especifica nada - posible a partir de .NET 3.5 SP1), o (el enfoque que yo prefiera) cualquier cosa que etiquete con un atributo [DataMember].

Así que lo mejor que puede hacer es marcar su clase con un atributo [DataContract], y todos los miembros (propiedades, campos, etc.) que realmente desea en su contrato de datos con un atributo [DataMember].

DataContractSerializer en realidad no permitir un control mucho más que eso - se puede definir con toda claridad (el uso de este "OPT" enfoque explícito) lo obtiene serializado, pero tiene poco o ningún control sobre cómo se serializa

¿Pero realmente lo necesita? ¿DE VERDAD?

Si es así, es probable que tenga que utilizar el XmlSerializer para ese proceso de serialización lugar - no se puede obtener un mayor control sobre cómo se serializan cosas (pero como un inconveniente, XmlSerializer va a serializar cada propiedad pública que no es explícitamente marcado con un atributo [XmlIgnore] - un esquema de "exclusión voluntaria").

Consulte Dan Rigsby's blog post sobre las diferencias entre DataContractSerializer y XmlSerializer y lo que cada uno de ellos tiene para ofrecer.

+0

Quiero que serialice todas las propiedades, XMLSerializer ni siquiera es una opción ya que mi objeto tiene un IList. Estaba preguntando sobre el esquema de nombres, ya que sería más fácil en mis documentos de transformación si las propiedades coincidieran exactamente con mis objetos de clase. –

+0

¿ha decorado su clase y propiedades con atributos [DataMember]? Puede definir un nombre con los siguientes: [DataMember (Name = "xyz")] - ¿Eso ayuda en su caso? –

+0

¿ha decorado las clases que terminarán dentro de su IList con el atributo [DataContract] y [DataMember]? Parece casi como si no ... –

5

Los nombres de los elementos largos (como, _x003C_Created_x003E_k__BackingField) los crea .NET cuando utiliza propiedades automáticas.

Si las cambió a propiedades con campos de respaldo, en su lugar usarían sus nombres de campo de respaldo. Puede hacerlo sin agregar ningún atributo a su código.

(Más allá de eso, simplemente añadiendo un atributo [DataContract] a su definición de clase será poner en orden su XML mucho - aunque no completamente.)

+0

Tendré que comprobar qué diferencia hace, puedo aceptar colocar un atributo en el nivel de clase, especialmente dado que estas clases son datos, incluso si no están expuestas a través de WCF –

+1

Me interesa su experiencia. La serialización parece estar mal definida y adolece de múltiples soluciones. –

0

me encontré con el mismo problema, al fin, por lo que sólo necesita para agregar [DataContract] 和 [DataMember] al modelo.

+1

Esta respuesta se marcó automáticamente como de baja calidad debido a su longitud y contenido. [La brevedad es aceptable, pero las explicaciones más completas son mejores.] (Http://stackoverflow.com/help/how-to-answer) –

Cuestiones relacionadas