Chr*_*ght 14 c# xml serialization xml-serialization
我试图使用XmlSerializer和继承序列化一些对象,但我在排序结果时遇到了一些问题.
下面是一个类似于我设置的示例:〜
public class SerializableBase
{
[XmlElement(Order = 1)]
public bool Property1 { get; set;}
[XmlElement(Order = 3)]
public bool Property3 { get; set;}
}
[XmlRoot("Object")]
public class SerializableObject1 : SerializableBase
{
}
[XmlRoot("Object")]
public class SerializableObject2 : SerializableBase
{
[XmlElement(Order = 2)]
public bool Property2 { get; set;}
}
Run Code Online (Sandbox Code Playgroud)
我想要的结果如下:〜
<Object>
<Property1></Property1>
<Property2></Property2>
<Property3></Property3>
</Object>
Run Code Online (Sandbox Code Playgroud)
但是我得到的结果是:〜
<Object>
<Property1></Property1>
<Property3></Property3>
<Property2></Property2>
</Object>
Run Code Online (Sandbox Code Playgroud)
有谁知道它是否可能或任何替代方案?
谢谢
Nad*_*zie 19
从技术上讲,从纯xml的角度来看,我想说这可能是一件坏事.
.NET隐藏了XmlSerialization之类的复杂功能 - 在这种情况下,它隐藏了序列化xml应符合的模式.
推断的模式将使用序列元素来描述基类型和扩展类型.这需要严格的排序 - 即使反序列化器不那么严格并且接受乱序元素.
在xml架构中,在定义扩展类型时,子类中的其他元素必须位于基类的元素之后.
你本质上有一个类似的架构(为清楚起见,删除了xml-y标签)
base
sequence
prop1
prop3
derived1 extends base
sequence
<empty>
derived2 extends base
sequence
prop2
Run Code Online (Sandbox Code Playgroud)
没有办法在prop1和prop3之间插入占位符来指示派生xml的属性可以去哪里.
最后,您的数据格式与业务对象之间存在不匹配.可能你最好的选择是定义一个对象来处理你的xml序列化.
例如
[XmlRoot("Object")
public class SerializableObjectForPersistance
{
[XmlElement(Order = 1)]
public bool Property1 { get; set; }
[XmlElement(Order = 2, IsNullable=true)]
public bool Property2 { get; set; }
[XmlElement(Order = 3)]
public bool Property3 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这会将xml序列化代码与对象模型分开.将SerializableObject1或SerializableObject2中的所有值复制到SerializableObjectForPersistance,然后将其序列化.
从本质上讲,如果您希望对序列化xml的格式进行这样的特定控制,而这种格式与期望的xml序列化框架不相符,那么您需要解耦业务对象设计(在这种情况下为继承结构)以及序列化的责任.业务对象.
编辑:这种方法不起作用。我已经离开了帖子,以便人们可以避免这种想法。
序列化程序以递归方式执行。这样做有好处;在反序列化时,反序列化过程可以读取基类,然后是派生类。这意味着派生类的属性没有在基类的属性之前设置,这可能会导致问题。
如果这真的很重要(我不确定为什么按顺序排列这些很重要)那么你可以试试这个——
1) 使基类的 Property1 和 Property3 成为虚拟的。2) 用派生类中的琐碎属性覆盖它们。例如
public class SerializableBase
{
[XmlElement(Order = 1)]
public virtual bool Property1 { get; set;}
[XmlElement(Order = 3)]
public virtual bool Property3 { get; set;}
}
[XmlRoot("Object")]
public class SerializableObject1 : SerializableBase
{
}
[XmlRoot("Object")]
public class SerializableObject2 : SerializableBase
{
[XmlElement(Order = 1)]
public override bool Property1
{
get { return base.Property1; }
set { base.Property1 = value; }
}
[XmlElement(Order = 2)]
public bool Property2 { get; set;}
[XmlElement(Order = 3)]
public override bool Property3
{
get { return base.Property3; }
set { base.Property3 = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
这将属性的具体实现放在最派生的类上,并且应该遵守顺序。
看起来 XmlSerializer 类序列化基类型,然后按该顺序序列化派生类型,并且仅单独尊重每个类中的 Order 属性。即使顺序不完全是您想要的,它仍然应该正确反序列化。如果您确实必须有这样的顺序,您将需要编写一个自定义 xml 序列化程序。我会警告您不要这样做,因为 .NET XmlSerializer 为您做了很多特殊处理。您能描述一下为什么您需要按照您提到的顺序进行操作吗?