C# 无法使用XML反序列化程序将XML反序列化到列表中

C# 无法使用XML反序列化程序将XML反序列化到列表中,c#,deserialization,xmlserializer,C#,Deserialization,Xmlserializer,这是我上一个问题的后续内容 公共类MeterWalkOrder { 公共气象秩序() { 仪表=新列表(); } 公共字符串名称{get;set;} [XmlIgnore] 公共列表{get;set;} [XmlArrayItem(ElementName=“Meter”)] [XmlArray(ElementName=“米”)] 公共列表序列化参数 { 得到 { 返回仪表.Cast().ToList(); } 设置 { 仪表=新列表(值); } } } 公共接口流量计{ int MeterID{

这是我上一个问题的后续内容

公共类MeterWalkOrder
{
公共气象秩序()
{
仪表=新列表();
}
公共字符串名称{get;set;}
[XmlIgnore]
公共列表{get;set;}
[XmlArrayItem(ElementName=“Meter”)]
[XmlArray(ElementName=“米”)]
公共列表序列化参数
{
得到
{
返回仪表.Cast().ToList();
}
设置
{
仪表=新列表(值);
}
}
}
公共接口流量计{
int MeterID{get;set;}
}
公共类仪表:万用表{
公共int MeterID{get;set;}
公共字符串序列号{get;set;}
}
}
我正在使用下面的扩展方法将XML反序列化回我的对象(理想情况下,我希望扩展方法远离对象,但我对扩展方法不太熟悉,所以我现在就这样离开了)

公共静态类序列化扩展
{
公共静态T LoadFromXML(此字符串xmlString)
{
T返回值=默认值(T);
XmlSerializer serial=新的XmlSerializer(typeof(T));
StringReader=新的StringReader(xmlString);
对象结果=串行。反序列化(读取器);
if(result!=null&&result为T)
{
返回值=((T)结果);
}
reader.Close();
返回值;
}
……但是,当我给出下面的XML时

<?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>

红色路线
1.
12345
2.
东南方
没有电表吗


有人知道是什么导致了这个问题吗?XML是有效的,SerializableMeters只是一个读取和写入米的属性,但由于在序列化中使用接口的已知问题,它将其转换为一个具体的类。

问题是
XmlSerializer
反序列化引用类im的属性按以下方式执行IList
IList

  • 它调用getter来获取列表。如果为null,它将分配一个列表并通过setter进行设置。它在读取列表时会将列表保存在某个局部变量中

  • 它反序列化每个列表元素,并将其添加到它所持有的列表中

  • 就是这样,它以后从不调用包含类的列表属性设置器

  • 您可以通过将
    列表
    替换为
    可观察集合
    ,并在集合更改时设置调试侦听器来验证这一点:

        [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());
        } 
    
    正如你所看到的,这个列表从来没有倒退过

    幸运的是,有一个简单的替代方法。如果返回代理数组而不是代理列表,
    XmlSerializer
    将分配数组本身,填充它,并通过setter进行设置——这正是您想要的

        [XmlArrayItem(ElementName = "Meter")]
        [XmlArray(ElementName = "Meters")]
        public Meter [] SerializableMeters
        {
            get
            {
                return Meters.Cast<Meter>().ToArray();
            }
            set
            {
                Meters = new List<IMeter>(value.Cast<IMeter>());
            }
        }
    
    [XmlArrayItem(ElementName=“Meter”)]
    [XmlArray(ElementName=“米”)]
    公用电表[]串行化电表
    {
    得到
    {
    返回仪表.Cast().ToArray();
    }
    设置
    {
    米=新列表(value.Cast());
    }
    }
    
    后来

        var meters = xml.LoadFromXML<MeterWalkOrder>();
        Debug.Assert(meters.Meters.Count == 2); // No assert.
    
    var meters=xml.LoadFromXML();
    Debug.Assert(meters.meters.Count==2);//无断言。
    
    为什么需要SerializableMeters?为什么不直接序列化Meters属性?我无法直接序列化它,因为它是一个不受支持的接口列表。我不想将其更改为使用具体类,因为我们总是将代码转换为接口而不是具体类
    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
    
        [XmlArrayItem(ElementName = "Meter")]
        [XmlArray(ElementName = "Meters")]
        public Meter [] SerializableMeters
        {
            get
            {
                return Meters.Cast<Meter>().ToArray();
            }
            set
            {
                Meters = new List<IMeter>(value.Cast<IMeter>());
            }
        }
    
        var meters = xml.LoadFromXML<MeterWalkOrder>();
        Debug.Assert(meters.Meters.Count == 2); // No assert.