我们在java服务器上创建了一个具有“自定义对象和属性”的项目,并且需要C#客户机上的这些数据。
例如,自定义对象'A‘有属性'B','C’。“B”和“C”都是由客户在运行时描述的。服务器以XML将此发送给我们,类似于:
<A>
<B> B Data </B>
<C> C Data </C>
</A>我们创建了一个实现IXmlSerializable的类,用于读写xml,用于服务器将自定义属性填充到字典中。
public class CustomObject : IXmlSerializable
{
private Dictionary<String, String> attributes;
public void ReadXml(XmlReader reader)
{
attributes = XDocument.Parse(reader.ReadOuterXml()).Root.Elements()
.ToDictionary(xElm => xElm.Name.LocalName, xElm => xElm.Value)
}
// More Serialization logic for IXmlSerializable is here
}该项目很慢,我们希望使用更快的DataContract序列化。我们通过在属性上显式指定硬编码的DataContract (如'B‘、'C')在示例上进行测试。但是,在我们的用例中,在编译时不知道属性。我们可以查询服务器上的属性列表类型'A‘。
如何对运行时定义的属性使用DataContract?
发布于 2016-05-26 08:53:46
DataContractSerializer不支持允许任意未知元素的显式数据契约。XmlSerializer通过[XmlAnyElementAttribute]支持这一点,但正如答案使用[XmlAnyElement]中所述,数据契约没有相同的功能。
您的类可以实现IExtensibleDataObject。它类似于[XmlAnyElement],是为前向兼容的数据合同设计的。不幸的是,在这种情况下,未知的元素存储在一个不透明的ExtensionDataObject中,没有明显的方法来访问这些值。虽然从这样一个对象(请参阅这里)中提取XML是可能的,但它并不明显,而且不太可能比当前代码更具性能,因为它需要在包装器类中重新序列化ExtensionDataObject,然后解析结果。
关于性能的一个注意事项--当您执行XDocument.Parse(reader.ReadOuterXml())时,参考源显示您正在有效地解析XML,然后将其通过XmlWriter流到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性能问题中,报告的类似优化的改进率为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的正确方法?。
https://stackoverflow.com/questions/37454156
复制相似问题