c# - 如何从 C# 中的通用接口派生的 XML 反序列化子集合
问题描述
我正在尝试反序列化包含从通用接口派生的子项的类。这是我的界面和两个示例类:
public interface IItem<T> : IXmlSerializable
{
T Value { get; set; }
string Name { get; set; }
List<IItem<T>> ChildItems { get; set; }
}
public class TypeA : IItem<string>
{
public string Value { get; set; }
public string Name { get; set; }
public List<IItem<string>> ChildItems { get; set; }
public TypeA()
{
ChildItems = new List<IItem<string>>();
}
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
var userQuery = new UserQuery();
Func<string, string> converter = value => value;
userQuery.ReadFromXml(reader, this, converter);
}
public void WriteXml(XmlWriter writer)
{
var userQuery = new UserQuery();
userQuery.WriteToXml(this, writer);
}
}
public class TypeB : IItem<int>
{
public int Value { get; set; }
public string Name { get; set; }
public List<IItem<int>> ChildItems { get; set; }
public TypeB()
{
ChildItems = new List<IItem<int>>();
}
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
var userQuery = new UserQuery();
Func<string, int> converter = value => Convert.ToInt16(value);
userQuery.ReadFromXml<int>(reader, this, converter);
}
public void WriteXml(XmlWriter writer)
{
var userQuery = new UserQuery();
userQuery.WriteToXml(this, writer);
}
}
我已经阅读了很多 SO 文章并得出结论,我需要使用 IXmlSerializable 接口来实现我自己的序列化。到目前为止,序列化效果很好!这是我用来序列化的方法:
public void WriteToXml<T>(IItem<T> item, XmlWriter writer)
{
writer.WriteElementString("Value", item.Value.ToString());
writer.WriteElementString("Name", item.Name);
writer.WriteStartElement("ChildItems");
foreach (var child in item.ChildItems)
{
// i want the name of the type to be the element name
writer.WriteStartElement(child.GetType().Name);
child.WriteXml(writer);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
我遇到的问题是反序列化子项。我反序列化孩子的方法如下所示:
public void ReadFromXml<T>(XmlReader reader, IItem<T> item, Func<string, T> parseExpectedValue)
{
reader.MoveToContent();
reader.ReadToFollowing("Value");
item.Value = parseExpectedValue(reader.ReadElementString("Value"));
reader.ReadToFollowing("Name");
item.Name = reader.ReadElementString("Name");
// todo: how to implement reading of child items ??
reader.ReadToFollowing("ChildItems");
// the statement below throws an InvalidOperationException with
// the inner exception message: Unexpected node type Element. ReadElementString method can only be called on elements with simple or empty content
var value = reader.ReadElementString();
}
对于序列化和反序列化,我使用以下方法:
public string Serialize<T>(T item)
{
var type = item.GetType();
var serializer = new XmlSerializer(type);
var serializedItem = string.Empty;
using (var stringWriter = new StringWriter())
{
serializer.Serialize(stringWriter, item);
serializedItem = stringWriter.ToString();
}
return serializedItem;
}
public T Deserialize<T>(string serializedItem) where T : class
{
T item = null;
try
{
var type = typeof(T);
var serializer = new XmlSerializer(type);
using (var stringReader = new StringReader(serializedItem))
{
item = (T)serializer.Deserialize(stringReader);
}
}
catch (System.Exception ex)
{
ex.Dump();
}
return item;
}
当我序列化以下对象时,XML 结果如下所示:
var testItemA = new TypeA()
{
Name = "TestTypeA",
Value = "TestValue",
ChildItems = new List<UserQuery.IItem<string>>()
{
new TypeA() { Name = "Str Child 1", Value = "Str Child Value 1", },
new TypeA() { Name = "Str Child 2", Value = "Str Child Value 2", ChildItems = new List<UserQuery.IItem<string>>(){ new TypeA(){ Name = "Str Child 3", Value = "Test Value 3" } }},
}
};
var testItemB = new TypeB()
{
Name = "TestTypeB",
Value = 1234,
ChildItems = new List<UserQuery.IItem<int>>()
{
new TypeB() { Name = "Child1", Value = 100, },
new TypeB() { Name = "Child2", Value = 200, }
}
};
XML 输出:
<?xml version="1.0" encoding="utf-16"?>
<TypeA>
<Value>TestValue</Value>
<Name>TestTypeA</Name>
<ChildItems>
<TypeA>
<Value>Str Child Value 1</Value>
<Name>Str Child 1</Name>
<ChildItems />
</TypeA>
<TypeA>
<Value>Str Child Value 2</Value>
<Name>Str Child 2</Name>
<ChildItems>
<TypeA>
<Value>Test Value 3</Value>
<Name>Str Child 3</Name>
<ChildItems />
</TypeA>
</ChildItems>
</TypeA>
</ChildItems>
</TypeA>
<?xml version="1.0" encoding="utf-16"?>
<TypeB>
<Value>1234</Value>
<Name>TestTypeB</Name>
<ChildItems>
<TypeB>
<Value>100</Value>
<Name>Child1</Name>
<ChildItems />
</TypeB>
<TypeB>
<Value>200</Value>
<Name>Child2</Name>
<ChildItems />
</TypeB>
</ChildItems>
</TypeB>
我知道我必须遍历 XML 中的子元素,但是我必须使用 XmlReader 的哪些方法?
解决方案
推荐阅读
- kubernetes - PVC 具有非绑定阶段(“待定”)
- rest - 如何知道哪个 fareComponent 与 BargainFinderMaxRS 中的段相关联
- mysql - WITH (...) IF ... IN ... 在 MySQL 触发器中
- python - 编写一个名为 index_of_smallest 的函数,它接受一个整数列表
- c++ - 我们如何使用下面的集合构造函数示例构造集合元素?
- r - 将 S4 对象转换为数据框 (R) 的一般方法
- ios - 如何正确设置 RN AccessibilityInfo setAccessibilityFocus
- javascript - 用javascript/html分隔男性和女性名字?
- excel - 如何编写自定义格式以使 3.33 显示为“3.33”但 3 显示为“3”?
- git - 具有两个分支的存储库与远程不同,如何修复?