c# - एक्सएमएल सीरियलाइजेशन-.NET 4.0 में अलग-अलग परिणाम



xml serialization (1)

कृपया नीचे दिया गया कोड देखें जो एक्सएमएल को 3 ऑब्जेक्ट्स की एक सूची वाली एक साधारण कक्षा को फाइल करने के लिए लिखता है। सूची में 3 ऑब्जेक्ट्स एक-दूसरे से उतरते हैं, बेस, व्युत्पन्न 1, व्युत्पन्न 2। मैं serialization के दौरान नाम ओवरराइड करने के लिए XMLArrayItemAttributes का उपयोग करें। यह .NET 3.0 में ठीक काम करता है, लेकिन अब .NET 4.0 में एक अलग परिणाम आउटपुट करता है। कृपया नीचे दिए गए आउटपुट देखें, विशेष रूप से दूसरे वंशज आइटम DerivedItem2 को नोट करते हुए।

क्या इसका कोई अनुभव है और मैं इसे .NET 4.0 में काम करने के लिए कैसे ठीक कर सकता हूं जैसा कि यह v3.5 में किया गया था?

ऐसा लगता है कि मैं ऑर्डर को नियंत्रित नहीं कर सकता जिसमें सरणी आइटम ओवरराइड हैं। यह उस क्रम में प्रतीत नहीं होता है जिसमें उन्हें XMLArrayItems में जोड़ा जाता है।

संपादित करें: मैंने फ्रेमवर्क संस्करण 4.0 और 4.5 के खिलाफ मोनो का उपयोग करके एक ही उदाहरण की कोशिश की है और यह उन लोगों के साथ ठीक काम करता है। क्या यह माइक्रोसॉफ्ट फ्रेमवर्क संस्करणों के साथ बस एक बग हो सकता है?

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);
    }
}

आउटपुट मूल (.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>

आउटपुट बदल गया (.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>

अद्यतन: .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>

अद्यतन: नीचे दिए गए app.config में डिबगिंग स्विच चालू करना, http://msdn.microsoft.com/en-us/library/aa302290.aspx से संदर्भित, मुझे लगता है कि जिस क्रम में सीरियलाइजेशन ओवरराइड लागू होता है वह है ऑर्डर के लिए अलग है जिसमें मैं ओवरराइड सरणी भरता हूं। किसी को भी कोई विचार है कि यह आदेश कैसे निर्धारित किया जाता है या ओवरराइड किया जाता है?

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

यह मुझे एसी # आउटपुट फ़ाइल देता है जो ओवरराइड ऑर्डर को गलत के रूप में दिखाता है:

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>)[email protected]);
        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);
}

खैर पैट,

.NET4 में आपके कोड का परीक्षण करते समय और .Net4.5 में बदलने के बाद मैंने एक ही समस्या को पुन: उत्पन्न करने में कामयाब रहा है ...

.Net4.5 में आउटपुट जैसा लगता है कि आपने .NET3 के लिए उद्धृत किया है

तो बस आगे बढ़ें और .Net4 छोड़ें और इसके बजाय बस .Net4.5 का उपयोग करें

इस समस्या का कारण ढांचे में स्मृति में वस्तुओं का निर्माण कैसे किया जाता है। .NET4 में वे शायद "बेस" से "व्युत्पन्न" और .Net3 और .Net4.5 में आयोजित किए जा रहे हैं ("व्युत्पन्न" से "आधार" तक वे मेरी राय में और सही मायने में राय रखते हैं। उस पर अधिक विशिष्ट होने के नाते, मेरा मानना ​​है कि इसमें:

.Net4 फ्रेमवर्क ऑब्जेक्ट इंस्टेंस को पॉइंटर के साथ आधार के प्रकार के रूप में संग्रहीत करता है।

.Net4.5 / .Net3 फ्रेमवर्क ऑब्जेक्ट इंस्टेंस को पॉइंटर्स के साथ मूल उदाहरण में व्युत्पन्न प्रकार के रूप में संग्रहीत करता है।

नियमित परिस्थितियों में ऑब्जेक्ट के साथ काम करते समय दोनों मामलों में आप एक ही परिणाम प्राप्त करते हैं।

मुझे याद है कि कचरा इकट्ठा करने में .net4.5 में कुछ सुधार हुए थे और मेरा मानना ​​है कि एमएस देवताओं ने प्रदर्शन को अनुकूलित करने के लिए यह चीजों का हिस्सा है।

दोनों परीक्षणों में मैंने एक्सएमएल सीरिएलाइज़र (4.0) के उसी संस्करण के साथ काम किया





xml-serialization