如何强制XmlSerializer的序列化的元素作为编译类型的属性? [英] How to force a XmlSerializer to serialize elements as attributes of a compiled type?

查看:140
本文介绍了如何强制XmlSerializer的序列化的元素作为编译类型的属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经给了一些predefined XML类似这样:

 < XML版本=1.0编码=UTF-8&GT?;
<根的xmlns:XSD =htt​​p://www.w3.org/2001/XMLSchema的xmlns:XSI =htt​​p://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 的五倍。它希望有一个后盾名单,其中有相同的每次通话,哪些是不能为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆