c# - XML Serialization - different result in .NET 4.0 -
please see code below writes xml out file simple class containing list of 3 objects. 3 objects in list descend each other, base, derived1, derived2. use xmlarrayitemattributes override names during serialization. works fine in .net 3.0, outputs different result in .net 4.0. please see below outputs, noting second descendant item deriveditem2.
has experience , how might fix work in .net 4.0 did in v3.5?
it seems cannot control order in array items overridden. doesn't appear order in added xmlarrayitems.
edit: i've tried same example using mono against framework versions 4.0 , 4.5 , works fine those. bug microsoft framework versions?
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(); (int = 0; < 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 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); } }
output 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>
output changed (.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>
update: output .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>
update: turning on debugging switch in app.config below, referenced http://msdn.microsoft.com/en-us/library/aa302290.aspx , find order in serialization applies overrides different order in fill override array. idea how order determined or overridden?
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.diagnostics> <switches> <add name="xmlserialization.compilation" value="4" /> </switches> </system.diagnostics> </configuration>
this gives me c# output file shows override order incorrect:
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> = (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); (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 global::windowsformsapplication1.deriveditem) { writeserializable((system.xml.serialization.ixmlserializable)((global::windowsformsapplication1.deriveditem)ai), @"deriveditem", @"", true, true); } else if (ai global::windowsformsapplication1.baseitem) { writeserializable((system.xml.serialization.ixmlserializable)((global::windowsformsapplication1.baseitem)ai), @"baseitem", @"", true, true); } else if (ai 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); }
well pat,
i have managed reproduce same problem when testing code in .net4 , changing .net4.5...
in .net4.5 output seems same quoted .net3
so go ahead , skip .net4 , instead use .net4.5
reason problem originated how objects constructed in memory in frameworks. in .net4 being held "base" "derived" , in .net3 , .net4.5 held (more correctly in opinion , matter of opinion) "derived" "base". being more specific on that, believe in:
.net4 framework stores object instance type of base pointer derived instance.
.net4.5/.net3 framework stores object instance type of derived pointers base instance.
in both cases end getting same result when working object in regular scenarios.
i remember reading garbage collecting had improvements in .net4.5 , believe part of things ms devs changed optimize performance.
in both tests worked same version of xml serializer (4.0)
Comments
Post a Comment