首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DataContract + IxmlSerializable

DataContract + IxmlSerializable
EN

Stack Overflow用户
提问于 2016-05-26 07:25:00
回答 1查看 846关注 0票数 0

我们在java服务器上创建了一个具有“自定义对象和属性”的项目,并且需要C#客户机上的这些数据。

例如,自定义对象'A‘有属性'B','C’。“B”和“C”都是由客户在运行时描述的。服务器以XML将此发送给我们,类似于:

代码语言:javascript
复制
<A>
    <B> B Data </B>
    <C> C Data </C>
</A>

我们创建了一个实现IXmlSerializable的类,用于读写xml,用于服务器将自定义属性填充到字典中。

代码语言:javascript
复制
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?

EN

回答 1

Stack Overflow用户

发布于 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一次,如下所示:

代码语言:javascript
复制
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字典:

代码语言:javascript
复制
    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的正确方法?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37454156

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档