serialize serializar net into example deserializar c# .net xml serialization xml-serialization

c# - serializar - Serialización XML: resultado diferente en.NET 4.0



system xml serialization xmlserializer vb net (1)

Bueno Pat,

He logrado reproducir el mismo problema al probar tu código en .Net4 y luego cambiar a .Net4.5 ...

En .Net4.5 el resultado parece ser el mismo que el que citó para .Net3

Así que simplemente sigue y omite .Net4 y en su lugar solo usa .Net4.5

La razón de este problema se origina en cómo se construyen los objetos en la memoria en los marcos. En .net4 probablemente estén retenidos de "base" a "derivado" y en .Net3 y .Net4.5 se mantienen (más correctamente en mi opinión y es una cuestión de opinión) de "derivado" a "base". Siendo más específico en eso, creo que en:

.Net4 el marco almacena la instancia del objeto como tipo de base con el puntero a la instancia derivada.

.Net4.5 / .Net3 el marco almacena la instancia del objeto como tipo de derivada con punteros a la instancia base.

En ambos casos, terminas obteniendo el mismo resultado cuando trabajas con el objeto en escenarios normales.

Recuerdo haber leído que la recolección de basura tenía algunas mejoras en .net4.5 y creo que esto es solo una parte de las cosas que los desarrolladores MS modificaron para optimizar el rendimiento.

En ambas pruebas trabajé con la misma versión de XML Serializer (4.0)

Por favor, vea el siguiente código que escribe XML para presentar una clase simple que contiene una lista de 3 objetos. Los 3 objetos en la lista descienden uno del otro, Base, Derivados1, Derivados2. Yo uso XMLArrayItemAttributes para anular los nombres durante la serialización. Esto funciona bien en .NET 3.0, pero ahora arroja un resultado diferente en .NET 4.0. Por favor, consulte las Salidas a continuación, señalando específicamente el segundo elemento descendiente DerivedItem2.

¿Alguien ha tenido alguna experiencia con esto y cómo podría solucionarlo para trabajar en .NET 4.0 como lo hizo en v3.5?

Parece que no puedo controlar el orden en que los elementos de la matriz son anulados. No parece ser el orden en que se agregan a XMLArrayItems.

Editar: Acabo de probar el mismo ejemplo usando MONO contra las versiones de framework 4.0 y 4.5 y funciona bien con esos. ¿Podría ser solo un error con las versiones de Microsoft framework?

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Collections; using System.Xml.Serialization; using System.Xml; using System.Xml.Schema; using System.IO; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { TestGroup g = new TestGroup(); XmlSerializer s = new XmlSerializer(typeof(TestGroup), g.GetOverrides()); TextWriter w = new StreamWriter("c://#//test.xml"); s.Serialize(w, g); w.Close(); } } public class TestGroup { public List<BaseItem> Items { get; set; } public TestGroup() { Items = new List<BaseItem>(); BaseItem b = new BaseItem(); b.BaseName = "Base Name"; Items.Add(b); DerivedItem d1 = new DerivedItem(); d1.BaseName = "D1"; d1.DerivedName = "D1"; Items.Add(d1); DerivedItem2 d2 = new DerivedItem2(); d2.BaseName = "D2"; //d2.DerivedName = "D2"; d2.Derived2Name = "D2"; Items.Add(d2); } public XmlAttributeOverrides GetOverrides() { XmlAttributes atts = new XmlAttributes(); for (int i = 0; i < Items.Count; i++) { BaseItem b = Items[i]; Type ItemType = b.GetType(); XmlArrayItemAttribute ItemAtt = new XmlArrayItemAttribute(); ItemAtt.ElementName = ItemType.Name; ItemAtt.Type = ItemType; atts.XmlArrayItems.Add(ItemAtt); } XmlAttributeOverrides attOvers = new XmlAttributeOverrides(); attOvers.Add(typeof(TestGroup), "Items", atts); return attOvers; } } public class BaseItem : IXmlSerializable { public string BaseName; public XmlSchema GetSchema() { return null; } public void ReadXml(XmlReader reader) { // not required for example } public virtual void WriteXml(XmlWriter writer) { writer.WriteElementString("BaseName", this.BaseName); } } public class DerivedItem: BaseItem { public string DerivedName; public override void WriteXml(XmlWriter writer) { base.WriteXml(writer); writer.WriteElementString("DerivedName", this.DerivedName); } } public class DerivedItem2: DerivedItem { public string Derived2Name; public override void WriteXml(XmlWriter writer) { base.WriteXml(writer); writer.WriteElementString("Derived2Name", this.Derived2Name); } }

Salida original (.NET 3.0):

<?xml version="1.0" encoding="utf-8"?> <TestGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Items> <BaseItem> <BaseName>Base Name</BaseName> </BaseItem> <DerivedItem> <BaseName>D1</BaseName> <DerivedName>D1</DerivedName> </DerivedItem> <DerivedItem2> <BaseName>D2</BaseName> <DerivedName /> <Derived2Name>D2</Derived2Name> </DerivedItem2> </Items> </TestGroup>

Salida modificada (.NET 4.0):

<?xml version="1.0" encoding="utf-8"?> <TestGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Items> <BaseItem> <BaseName>Base Name</BaseName> </BaseItem> <DerivedItem> <BaseName>D1</BaseName> <DerivedName>D1</DerivedName> </DerivedItem> <DerivedItem> <BaseName>D2</BaseName> <DerivedName /> <Derived2Name>D2</Derived2Name> </DerivedItem> </Items> </TestGroup>

Actualización: salida de .NET 4.5

<?xml version="1.0" encoding="utf-8"?> <TestGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Items> <BaseItem> <BaseName>Base Name</BaseName> </BaseItem> <BaseItem> <BaseName>D1</BaseName> <DerivedName>D1</DerivedName> </BaseItem> <DerivedItem2> <BaseName>D2</BaseName> <DerivedName /> <Derived2Name>D2</Derived2Name> </DerivedItem2> </Items> </TestGroup>

Actualización: Al activar el conmutador de depuración en la aplicación.config como se indica a continuación, a la que se hace referencia en http://msdn.microsoft.com/en-us/library/aa302290.aspx , encuentro que el orden en que la serialización aplica las anulaciones es diferente al orden en el que llene la matriz de anulación. Alguien tiene alguna idea de cómo se determina o se anula esta orden?

<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.diagnostics> <switches> <add name="XmlSerialization.Compilation" value="4" /> </switches> </system.diagnostics> </configuration>

Esto me da un archivo de salida de CA # que muestra el orden de anulación como incorrecto:

void Write2_TestGroup(string n, string ns, global::WindowsFormsApplication1.TestGroup o, bool isNullable, bool needType) { if ((object)o == null) { if (isNullable) WriteNullTagLiteral(n, ns); return; } if (!needType) { System.Type t = o.GetType(); if (t == typeof(global::WindowsFormsApplication1.TestGroup)) { } else { throw CreateUnknownTypeException(o); } } WriteStartElement(n, ns, o, false, null); if (needType) WriteXsiType(@"TestGroup", @""); { global::System.Collections.Generic.List<global::WindowsFormsApplication1.BaseItem> a = (global::System.Collections.Generic.List<global::WindowsFormsApplication1.BaseItem>)((global::System.Collections.Generic.List<global::WindowsFormsApplication1.BaseItem>)o.@Items); if (a != null){ WriteStartElement(@"Items", @"", null, false); for (int ia = 0; ia < ((System.Collections.ICollection)a).Count; ia++) { global::WindowsFormsApplication1.BaseItem ai = (global::WindowsFormsApplication1.BaseItem)a[ia]; if ((object)(ai) != null){ if (ai is global::WindowsFormsApplication1.DerivedItem) { WriteSerializable((System.Xml.Serialization.IXmlSerializable)((global::WindowsFormsApplication1.DerivedItem)ai), @"DerivedItem", @"", true, true); } else if (ai is global::WindowsFormsApplication1.BaseItem) { WriteSerializable((System.Xml.Serialization.IXmlSerializable)((global::WindowsFormsApplication1.BaseItem)ai), @"BaseItem", @"", true, true); } else if (ai is global::WindowsFormsApplication1.DerivedItem2) { WriteSerializable((System.Xml.Serialization.IXmlSerializable)((global::WindowsFormsApplication1.DerivedItem2)ai), @"DerivedItem2", @"", true, true); } else if ((object)(ai) != null){ throw CreateUnknownTypeException(ai); } } } WriteEndElement(); } } WriteEndElement(o); }