C# xml 反序列化意外忽略 List<> 属性

C# xml deserialization ignoring List<> properties unexpectedly

因为 XmlSerializer 不适用于字典,所以我在字典上使用了 XmlIgnore 属性,并使用中介 List<> 属性 将字典呈现为列表,确实如此 使用序列化。但是,我的 List<> 属性 在反序列化时被忽略了。 (没有抛出错误,也没有引发序列化事件。)为什么?

[XmlIgnore]
public Dictionary<string, string> ConnectionStrings { get; set; }

这是应该用于 de/serialization 的 "surrogate" 列表 属性。就像我说的,这适用于序列化,但 属性 在反序列化期间被忽略。我正在尝试理解 why/what 来解决它....

public List<ConnectionItem> SerializedConnections
{
    get 
    { 
        return ConnectionStrings.Select(keyPair => new ConnectionItem() { Name = keyPair.Key, ConnectionString = keyPair.Value }).ToList(); 
    }
    set 
    {
        ConnectionStrings = new Dictionary<string, string>();
        foreach (var ci in value) ConnectionStrings.Add(ci.Name, ci.ConnectionString);
    }
}

我尝试在我的 SerializedConnections 属性 的 set 访问器中设置断点,但它从未命中。

这永远不会像您假设的那样工作。在反序列化期间,XmlSerializer 调用 getter 来检索可能为空的 List<T> 实例,然后调用它的 Add(T item) 方法来填充它反序列化对象。

documentation in MSDN 特别指出:

The XmlSerializer gives special treatment to classes that implement IEnumerable or ICollection. A class that implements IEnumerable must implement a public Add method that takes a single parameter. The Add method's parameter must be of the same type as is returned from the Current property on the value returned from GetEnumerator, or one of that type's bases. A class that implements ICollection (such as CollectionBase) in addition to IEnumerable must have a public Item indexed property (indexer in C#) that takes an integer, and it must have a public Count property of type integer. The parameter to the Add method must be the same type as is returned from the Item property, or one of that type's bases. For classes that implement ICollection, values to be serialized are retrieved from the indexed Item property, not by calling GetEnumerator.

您设计的核心问题是 SerializedConnections 属性 的行为 作为数据生成器 。换句话说,每次调用 getter 都会返回一个新实例。属性不应该那样工作——只有方法才应该这样。

一个可能的解决方案是实现自定义集合,实现 IList<ConnectionItem> 并使用 Dictionary<string, string> 作为后备存储。然后 ConnectionStrings 属性,或者更好的私有字段,将是这种自定义类型,并且 SerializedConnections 属性 将在 serialization/deserialization.[=37 期间正确运行=]