C# 反序列化集合时未调用Setter
我正在尝试使用XmlSerializer进行一个非常简单的序列化:C# 反序列化集合时未调用Setter,c#,collections,setter,xmlserializer,C#,Collections,Setter,Xmlserializer,我正在尝试使用XmlSerializer进行一个非常简单的序列化: public struct XmlPerson { [XmlAttribute] public string Id { get; set; } [XmlAttribute] public string Name { get; set; } } public class GroupOfPeople { private Dictionary<string, string> _namesByI
public struct XmlPerson
{
[XmlAttribute] public string Id { get; set; }
[XmlAttribute] public string Name { get; set; }
}
public class GroupOfPeople
{
private Dictionary<string, string> _namesById = new Dictionary<string, string>();
//pseudo property for serialising dictionary to/from XML
public List<XmlPerson> _XmlPeople
{
get
{
var people = new List<XmlPerson>();
foreach (KeyValuePair<string, string> pair in _namesById )
people.Add(new XmlPerson() { Id = pair.Key, Name = pair.Value });
return people;
}
set
{
_namesById.Clear();
foreach (var person in value)
_namesById.Add(person.Id, person.Name);
}
}
}
您是否尝试过使用XmlArray属性 以您的示例为例,可能是这样的:
[XmlArray]
[XmlArrayItem(ElementName="XmlPerson")]
public List<XmlPerson> XmlPeople
[XmlArray]
[XmlArrayItem(ElementName=“XmlPerson”)]
公众人物名单
编辑:
在这里,请尝试以下结构:
public struct XmlPerson
{
[XmlAttribute] public string Id { get; set; }
[XmlAttribute] public string Name { get; set; }
}
public class GroupOfPeople
{
[XmlArray]
[XmlArrayItem(ElementName="XmlPerson")]
public List<XmlPerson> XmlPeople { get; set; }
}
public结构XmlPerson
{
[XmlAttribute]公共字符串Id{get;set;}
[XmlAttribute]公共字符串名称{get;set;}
}
公共阶层人群
{
[XmlArray]
[XmlArrayItem(ElementName=“XmlPerson”)]
公共列表XmlPeople{get;set;}
}
我认为将代码添加到列表的Setter中并不容易,所以在您实际需要时获取该字典怎么样
像这样:
private Dictionary<string, string> _namesById;
public Dictionary<string, string> NamesById
{
set { _namesById = value; }
get
{
if (_namesById == null)
{
_namesById = new Dictionary<string, string>();
foreach (var person in XmlPeople)
{
_namesById.Add(person.Id, person.Name);
}
}
return _namesById;
}
}
private Dictionary\u namesById;
公共字典namebyid
{
设置{u namesById=value;}
得到
{
if(_namesById==null)
{
_namesById=newdictionary();
foreach(XmlPeople中的var人员)
{
_namesById.Add(person.Id,person.Name);
}
}
返回_namesById;
}
}
通过这种方式,您可以从XML中获取项目,还可以保存您的字典。为了清晰起见,请回答:
已经进行了一些调试,发现XmlSerializer
没有为集合调用setter。
而是调用getter,然后将项添加到返回的集合中。因此,像Felipe这样的解决方案是必要的。在这个问题中,
\u XmlPeople
属性充当\u namesById
字典的“代理”,它是集合元素实际存储的地方。它的getter和setter在不同类型的集合之间转换
这不适用于反序列化,原因已在中指出。
(反序列化调用getter,然后将元素添加到它返回的“临时”集合中,然后丢弃该集合)
一般解决方案是将“代理集合”实现为一个单独的类,然后拥有一个作为代理集合的属性:
(在下面的代码中,“实际收集”是\u nameById
,MyItem
是XmlPerson
)
公共类MyProxyCollection:IList{
MyProxyCollection(…/*对实际集合的引用*/…){…}
//在这里实现IList
}
公共类MyModel{
MyProxyCollection\u代理;
公共MyModel(){
_代理=新的MyProxyCollection(…/*对实际集合的引用*/…);
}
//在这里,我们确保getter和setter始终返回对同一对象的引用
//集合对象。这确保我们将项添加到上的正确集合
//反序列化。
公共MyProxyCollection项{get;set;}
}
这确保获取/设置集合对象按预期工作。从不调用setter。我有一个断点在上面。保存时可以明显识别属性,但仍无法加载:/@GazTheDestroyer编辑了答案以包含一些代码示例。正在进行一些调试(请参见我的答案),但已将您的答案设置为正确,因为它确实解决了问题。把我的答案写清楚,以防其他人有问题。
public struct XmlPerson
{
[XmlAttribute] public string Id { get; set; }
[XmlAttribute] public string Name { get; set; }
}
public class GroupOfPeople
{
[XmlArray]
[XmlArrayItem(ElementName="XmlPerson")]
public List<XmlPerson> XmlPeople { get; set; }
}
private Dictionary<string, string> _namesById;
public Dictionary<string, string> NamesById
{
set { _namesById = value; }
get
{
if (_namesById == null)
{
_namesById = new Dictionary<string, string>();
foreach (var person in XmlPeople)
{
_namesById.Add(person.Id, person.Name);
}
}
return _namesById;
}
}
public class MyProxyCollection : IList<MyItem> {
MyProxyCollection(... /* reference to actual collection */ ...) {...}
// Implement IList here
}
public class MyModel {
MyProxyCollection _proxy;
public MyModel() {
_proxy = new MyProxyCollection (... /* reference to actual collection */ ...);
}
// Here we make sure the getter and setter always return a reference to the same
// collection object. This ensures that we add items to the correct collection on
// deserialization.
public MyProxyCollection Items {get; set;}
}