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 期间正确运行=]
因为 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
orICollection
. A class that implementsIEnumerable
must implement a publicAdd
method that takes a single parameter. TheAdd
method's parameter must be of the same type as is returned from theCurrent
property on the value returned fromGetEnumerator
, or one of that type's bases. A class that implementsICollection
(such asCollectionBase
) in addition toIEnumerable
must have a publicItem
indexed property (indexer in C#) that takes an integer, and it must have a publicCount
property of type integer. The parameter to theAdd
method must be the same type as is returned from theItem
property, or one of that type's bases. For classes that implementICollection
, values to be serialized are retrieved from the indexedItem
property, not by callingGetEnumerator
.
您设计的核心问题是 SerializedConnections
属性 的行为 作为数据生成器 。换句话说,每次调用 getter 都会返回一个新实例。属性不应该那样工作——只有方法才应该这样。
一个可能的解决方案是实现自定义集合,实现 IList<ConnectionItem>
并使用 Dictionary<string, string>
作为后备存储。然后 ConnectionStrings
属性,或者更好的私有字段,将是这种自定义类型,并且 SerializedConnections
属性 将在 serialization/deserialization.[=37 期间正确运行=]