不支持允许任意未知元素的显式数据协定DataContractSerializer
。 XmlSerializer
支持这个 via [XmlAnyElementAttribute]
,但如答案Using [XmlAnyElement]中所述,数据合同没有相同的功能。
你的班级可以实现IExtensibleDataObject
. 它与前向兼容的数据合约类似,[XmlAnyElement]
并且旨在用于前向兼容的数据合约。不幸的是,在这种情况下,未知元素存储在不透明ExtensionDataObject
的地方,没有明显的方法可以访问这些值。虽然可以从这样的对象中提取 XML(请参见此处),但它并不明显,并且不太可能比您当前的代码具有更高的性能,因为它需要重新序列化ExtensionDataObject
包装类内部,然后解析结果。
关于性能的一个注意事项 - 当您这样做时XDocument.Parse(reader.ReadOuterXml())
,参考源显示您正在有效地解析您的 XML,然后将其通过 a 流式传输XmlWriter
到 a StringWriter
,然后再次解析生成的字符串。XNode.ReadFrom()
您可以通过调用传入的阅读器仅解析一次 XML,而不是这样做,如下所示:
public class CustomObject : IXmlSerializable
{
private readonly Dictionary<String, String> attributes = new Dictionary<string, string>();
public IDictionary<string, string> Attributes { get { return attributes; } }
#region IXmlSerializable Members
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
{
return null;
}
void IXmlSerializable.ReadXml(XmlReader reader)
{
var element = XElement.ReadFrom(reader) as XElement;
if (element != null)
{
foreach (var item in element.Elements())
attributes.Add(item.Name.LocalName, (string)item);
}
}
void IXmlSerializable.WriteXml(XmlWriter writer)
{
// Do NOT write the wrapper element when writing.
foreach (var pair in attributes)
{
writer.WriteElementString(pair.Key, pair.Value);
}
}
#endregion
}
这应该比您当前的课程更高效。例如,在大型动态 XML 的 Web API 性能问题中,类似优化的报告改进为 40%。
更新
为了实现最佳性能IXmlSerializable
,您需要直接从XmlReader
使用的定制代码中读取内容。例如,以下将元素名称和值读入attributes
字典:
void IXmlSerializable.ReadXml(XmlReader reader)
{
if (reader.IsEmptyElement)
{
reader.Read();
return;
}
reader.Read();
while (reader.NodeType != XmlNodeType.EndElement)
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
var key = reader.Name;
var value = reader.ReadElementContentAsString();
attributes.Add(key, value);
break;
default:
// Comment, for instance.
reader.Read();
break;
}
}
// Consume the EndElement
reader.Read();
}
请参阅实现 IXmlSerializable 的正确方法?有关正确手动读取元素层次结构的一些一般准则。