无法反序列化XML转换使用XML解串器列表 [英] Cannot deserialize XML into a list using XML Deserializer

查看:147
本文介绍了无法反序列化XML转换使用XML解串器列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这从我刚才的问题是继接口序列化列表使用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方法​​设置它。它拥有榜上有名在一些局部变量,而阅读它。

  1. 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屋!

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