如何强制XmlSerializer的序列化的元素作为编译类型的属性? [英] How to force a XmlSerializer to serialize elements as attributes of a compiled type?
问题描述
我已经给了一些predefined XML类似这样:
< XML版本=1.0编码=UTF-8&GT?;
<根的xmlns:XSD =http://www.w3.org/2001/XMLSchema的xmlns:XSI =http://www.w3.org/2001/XMLSchema-instance>
<点>
<点X =1.345Y =7.45/>
<点X =1.123Y =5.564/>
<点X =3.34Y =2.5345/>
< /点>
<! - 和一堆其他属性和结构是完全序列化和XmlSerializer的序列化 - >
< /根>
和我的目标是反序列化到一个名单,其中,System.Windows.Point>
使用的XmlSerializer
实例反之亦然。所以我定义的类型如下所示:
[Serializable接口]
[XmlRoot(根)
公共类RootClass
{
公开名单< System.Windows.Point>点{获得;组; }
/ *和更多的属性* /
}
我的问题是,的XmlSerializer
除$ P $点的框架属性的XmlElement
。以它们是只读取和写入这样,但不作为属性的要求。
一个解决方案我想到了,被定义自定义点类型,它定义了 XmlAttribtueAttribute
的每个坐标财产。而这种自定义点被映射到 System.Windows.Point
结构。这看起来像以下内容:
[XmlIgnore]
公开名单<点>点{获得;组; }
[XmlArray(点)]
[XmlArrayItem(点)]
公开名单< CustomSerializedPoint> CustomSerializedPoints
{
{返回this.Points.ToCustomSerializedPointList(); }
集合{this.Points = value.ToPointList(); }
}
但这种解决方案我注意到,该二传手是不会被调用,而的XmlSerializer
要求 CustomSerializedPoints $ C的吸气剂$ C>的五倍。它希望有一个后盾名单,其中有相同的每次通话,哪些是不能为null。为了该要求,这对我来说是无解的,因为我需要保持
名单,其中,CustomSerializedPoints>
在内存中只是写使用属性,而不是元素的点。
所以,有一个人更practiable的解决方案?
此外我的XmlSerializer
code:
/ * ... * /
无功序列化=新的XmlSerializer(typeof运算(RootClass));
的TextReader的TextReader =新的StreamReader(file.xml);
(RootClass)serializer.Deserialize(TextReader的);
/ * ... * /
您可以改变一个类被序列化/反序列化通过改变在运行时的序列化属性的方式。 XmlAttributeOverrides
类提供了这样的可能性。下面的例子code正确deseralizes您所提供的XML:
XMLATTRIBUTES XA =新XMLATTRIBUTES();
XMLATTRIBUTES亚=新XMLATTRIBUTES();
xa.XmlAttribute =新XmlAttributeAttribute(X);
ya.XmlAttribute =新XmlAttributeAttribute(Y);
XmlAttributeOverrides XAO =新XmlAttributeOverrides();
xao.Add(typeof运算(System.Windows.Point)中,X,XA);
xao.Add(typeof运算(System.Windows.Point),Y,雅);
无功序列化=新的XmlSerializer(typeof运算(RootClass),XAO);
的TextReader的TextReader =新的StreamReader(file.xml);
VAR的结果=(RootClass)serializer.Deserialize(TextReader的);
I've given some predefined XML similar to this:
<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Points>
<Point X="1.345" Y="7.45" />
<Point X="1.123" Y="5.564" />
<Point X="3.34" Y="2.5345" />
</Points>
<!-- and a bunch of other attributes and structures which are perfectly serialized and deserialized by the XmlSerializer -->
</Root>
And my goal is to deserialize it into a List<System.Windows.Point>
using a XmlSerializer
instance and vice versa. Therefore I've defined type like the following:
[Serializable]
[XmlRoot("Root")]
public class RootClass
{
public List<System.Windows.Point> Points { get; set; }
/* and more properties */
}
My problem is that the XmlSerializer
interprets the framework properties as XmlElement
. In order to that they are only read and written as such, but not as attributes as required.
One solution I thought about, was defining a custom point type, which defines the XmlAttribtueAttribute
for each coordinate property. And this custom point gets mapped to the System.Windows.Point
structure. This looked like the following:
[XmlIgnore]
public List<Point> Points { get; set; }
[XmlArray("Points")]
[XmlArrayItem("Point")]
public List<CustomSerializedPoint> CustomSerializedPoints
{
get { return this.Points.ToCustomSerializedPointList(); }
set { this.Points = value.ToPointList(); }
}
But for this solution i've noticed, that the setter is never called, and the XmlSerializer
calls the getter of CustomSerializedPoints
about five times. It expects that there is a backing list, which has the same reference each call and which is never null. In order to that requirements, this is no solution for me, because I would need to keep the List<CustomSerializedPoints>
in memory just for writing the points using attributes instead of elements.
So has someone a more practiable solution?
Additionally my XmlSerializer
code:
/* ... */
var serializer = new XmlSerializer(typeof(RootClass));
TextReader textReader = new StreamReader("file.xml");
(RootClass)serializer.Deserialize(textReader);
/* ... */
You can change the way a class is being serialized/deserialized by altering its serialization attributes at runtime. XmlAttributeOverrides
class provides such possibility. The following example code correctly deseralizes the XML you've provided:
XmlAttributes xa = new XmlAttributes();
XmlAttributes ya = new XmlAttributes();
xa.XmlAttribute = new XmlAttributeAttribute("X");
ya.XmlAttribute = new XmlAttributeAttribute("Y");
XmlAttributeOverrides xao = new XmlAttributeOverrides();
xao.Add(typeof(System.Windows.Point), "X", xa);
xao.Add(typeof(System.Windows.Point), "Y", ya);
var serializer = new XmlSerializer(typeof(RootClass), xao);
TextReader textReader = new StreamReader("file.xml");
var result = (RootClass)serializer.Deserialize(textReader);
这篇关于如何强制XmlSerializer的序列化的元素作为编译类型的属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!