gpt4 book ai didi

c# - XML 序列化 - .NET 4.0 中的不同结果

转载 作者:IT王子 更新时间:2023-10-29 04:31:38 26 4
gpt4 key购买 nike

请参阅下面的代码,该代码将 XML 写出以归档一个包含 3 个对象列表的简单类。列表中的 3 个对象相互继承,Base、Derived1、Derived2。我使用 XMLArrayItemAttributes 在序列化期间覆盖名称。这在 .NET 3.0 中工作正常,但现在在 .NET 4.0 中输出不同的结果。请查看下面的输出,特别注意第二个后代项 DerivedItem2。

有没有人对此有任何经验以及我如何修复它以像在 v3.5 中那样在 .NET 4.0 中工作?

看来我无法控制覆盖数组项的顺序。它似乎不是它们添加到 XMLArrayItems 的顺序。

编辑:我刚刚针对框架版本 4.0 和 4.5 尝试了使用 MONO 的相同示例,并且在这些版本上运行良好。这可能只是 Microsoft 框架版本的错误吗?

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>

这给了我一个 c# 输出文件,它显示覆盖顺序不正确:

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

最佳答案

好吧,帕特,

我在 .Net4 中测试您的代码时重现了同样的问题,而不是更改为 .Net4.5...

在 .Net4.5 中,输出似乎与您引用的 .Net3 相同

所以继续前进并跳过 .Net4 而只是使用 .Net4.5

这个问题的起因在于框架中对象是如何在内存中构造的。在 .net4 中,它们可能是从“基础”到“派生”,而在 .Net3 和 .Net4.5 中,它们是从“派生”到“基础”(我认为更正确,这是一个意见问题)。更具体地说,我相信:

.Net4 框架将对象实例存储为带有指向派生实例指针的基类型。

.Net4.5/.Net3 框架将对象实例存储为带有指向基实例的指针的派生类型。

在这两种情况下,在常规场景中使用对象时,您最终会得到相同的结果。

我确实记得读过垃圾收集在 .net4.5 中有一些改进,我相信这只是 MS 开发人员为优化性能所做更改的一部分。

在这两个测试中,我使用了相同版本的 XML Serializer (4.0)

关于c# - XML 序列化 - .NET 4.0 中的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17853837/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com