无法反序列化XML转换使用XML解串器列表 [英] Cannot deserialize XML into a list using XML Deserializer
问题描述
这从我刚才的问题是继接口序列化列表使用XML序列化
This follows on from my previous question Serialize list of interfaces using XML Serialization
public class MeterWalkOrder
{
public MeterWalkOrder()
{
Meters = new List<IMeter>();
}
public String Name { get; set; }
[XmlIgnore]
public List<IMeter> Meters { get; set; }
[XmlArrayItem(ElementName = "Meter")]
[XmlArray(ElementName = "Meters")]
public List<Meter> SerializableMeters
{
get
{
return Meters.Cast<Meter>().ToList();
}
set
{
Meters = new List<IMeter>(value);
}
}
}
public interface IMeter {
int MeterID { get; set; }
}
public class Meter : IMeter {
public int MeterID { get; set; }
public string SerialNumber { get; set; }
}
}
我使用的扩展方法如下反序列化XML回到我的目标(理想情况下,我宁愿扩展方法是关闭的对象,但我不太舒服的扩展方法,所以我已经离开这样的现在)...
I am using the extension method below to deserialize the XML back into my object (ideally I would prefer the extension method to be off of object, but I not too comfortable with extension methods so I have left like this for now)...
public static class SerializationExtensions
{
public static T LoadFromXML<T>(this string xmlString)
{
T returnValue = default(T);
XmlSerializer serial = new XmlSerializer(typeof(T));
StringReader reader = new StringReader(xmlString);
object result = serial.Deserialize(reader);
if (result != null && result is T)
{
returnValue = ((T)result);
}
reader.Close();
return returnValue;
}
...然而,当我给下面的XML ....
....However, when I give the XML below....
<?xml version="1.0"?>
<MeterWalkOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Red Route</Name>
<Meters>
<Meter>
<MeterID>1</MeterID>
<SerialNumber>12345</SerialNumber>
</Meter>
<Meter>
<MeterID>2</MeterID>
<SerialNumber>SE</SerialNumber>
</Meter>
</Meters>
</MeterWalkOrder>
没有米的填充?
有谁知道什么可能导致这个问题? XML是有效的,并SerializeableMeters仅仅是读取和写入操作来米,但属性铸造它作为一个具体的类由于与使用接口系列化
Does anyone know what could cause this problem? The XML is valid and SerializeableMeters is simply a property that reads from and writes to Meters but casting it as a concrete class due to the known issues with using interfaces in serialization
推荐答案
的问题是,的XmlSerializer
反序列化的属性指的是一个类实现的IList< T>
以下列方式:
The problem is that XmlSerializer
deserializes a property referring to a class implementing IList<T>
in the following way:
它调用吸气剂来获得该列表。如果为null,它分配一个列表,并通过setter方法设置它。它拥有榜上有名在一些局部变量,而阅读它。
It calls the getter to get the list. If null, it allocates a list and sets it via the setter. It holds onto the list in some local variable while reading it.
据反序列化每个列表元素,并将其添加到它持有的列表中。
It deserializes each list element, and adds it to the list it is holding.
就是这样。它永远不会调用包含类的列表中的属性设置的算账。
And that's it. It never calls the containing class's list property setter afterwards.
您可以验证这一点更换你的列表<仪表>
与的ObservableCollection<仪表>
,并设置为集合更改时调试监听器:
You can verify this by replacing your List<Meter>
with an ObservableCollection<Meter>
, and setting a debug listener for when the collection changes:
[XmlArrayItem(ElementName = "Meter")]
[XmlArray(ElementName = "Meters")]
public ObservableCollection<Meter> SerializableMeters
{
get
{
Debug.WriteLine("Returning proxy SerializableMeters");
var list = new ObservableCollection<Meter>(Meters.Cast<Meter>());
list.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(list_CollectionChanged);
return list;
}
set
{
Debug.WriteLine("Setting proxy SerializableMeters");
Meters = new List<IMeter>(value.Cast<IMeter>());
}
}
static void list_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
var collection = (IList<Meter>)sender;
Debug.WriteLine("Proxy collection changed to include : ");
foreach (var item in collection)
Debug.WriteLine(" " + item.ToString());
}
这样做,你会看到如下调试输出:
Doing so, you'll see the following debug output:
Returning proxy SerializableMeters
Returning proxy SerializableMeters
Returning proxy SerializableMeters
Returning proxy SerializableMeters
Proxy collection changed to include :
Meter: 1, 12345
Proxy collection changed to include :
Meter: 1, 12345
Meter: 2, SE
正如你可以看到,该列表永远不会重新设置。
As you can see, the list is never set back.
幸运的是,有一个很不错的选择。如果返回的阵列的而不是代理的代理列表的的XmlSerializer
将分配数组本身,填充它,通过二传手设置 - !你想要什么这仅仅是
Luckily, there's an easy alternative. If you return a proxy array instead of a proxy List, XmlSerializer
will allocate the array itself, populate it, and set it via the setter -- which is just what you want!
[XmlArrayItem(ElementName = "Meter")]
[XmlArray(ElementName = "Meters")]
public Meter [] SerializableMeters
{
get
{
return Meters.Cast<Meter>().ToArray();
}
set
{
Meters = new List<IMeter>(value.Cast<IMeter>());
}
}
再后来
And then later
var meters = xml.LoadFromXML<MeterWalkOrder>();
Debug.Assert(meters.Meters.Count == 2); // No assert.
这篇关于无法反序列化XML转换使用XML解串器列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!