c# - 确定类如何使用反序列化 XML 的最有效方法

标签 c# xml serialization xsd

我有很多 xml 模式的 .xsd 文件

例子

XML 1.0 - xml_1_0.xml

<?xml version="1.0" encoding="UTF-8"?>
     <cars version="1.00">
         <car>Honda</car>
         <car>Ferrari</car>
     </cars>

XML 2.0 - xml_2_0.xml

<?xml version="1.0" encoding="UTF-8"?>
 <cars version="2.00">
     <car>
       <name>Honda</name>
       <color>White</color>
     </car>

     <car>
       <name>Honda</name>
       <color>Red</color>
     </car>
 </cars>

我像这样从 .xsd 创建我的类

xsd.exe cars_1_0.xsd /c

xsd.exe cars_2_0.xsd /c

像这样反序列化:

foreach(string file in files) {
     XmlDocument doc = new XmlDocument();
     doc.Load(file);    
     string version =   doc.SelectSingleNode("/Cars/@version").Value;

     if(version == "1.00")
     {
         Stream reader = new FileStream(file, FileMode.Open);
         XmlSerializer serializer = new XmlSerializer(typeof(v1.Cars));

         v1.Cars XML = new v1.Cars();
         XML = (v1.Cars)serializer.Deserialize(reader);
     } 
     else if(version == "2.00") 
     {
         Stream reader = new FileStream(file, FileMode.Open);
         XmlSerializer serializer = new XmlSerializer(typeof(v2.Cars));

         v2.Cars XML = new v2.Cars();
         XML = (v2.Cars)serializer.Deserialize(reader);
     }
}

有没有人知道更好的方法,或者有更好的性能?

最佳答案

您有多种选择,具体取决于您想走多远。一个相当非侵入性的选择是不使用 XmlDocument并避免多次加载流。例如,您现有的代码可以简化/精简为:

foreach (string file in files)
{
    using (var stream = new FileStream(file, FileMode.Open))
    {
        var settings = new XmlReaderSettings();
        settings.CloseInput = false;
        string version = "";
        using (var xmlReader = XmlReader.Create(stream))
        {
            if (xmlReader.ReadToFollowing("Cars"))
            {
                version = xmlReader.GetAttribute("version");
            }
            else
            {
                throw new XmlException("Could not get 'version' attribute of 'Cars' root element!");
            }                    
        }
        stream.Position = 0;
        if (version == "1.00")
        {
            XmlSerializer serializer = new XmlSerializer(typeof(v1.Cars));

            v1.Cars XML = new v1.Cars();
            XML = (v1.Cars)serializer.Deserialize(stream);
        }
        else if (version == "2.00")
        {
            XmlSerializer serializer = new XmlSerializer(typeof(v2.Cars));

            v2.Cars XML = new v2.Cars();
            XML = (v2.Cars)serializer.Deserialize(stream);

        }
    }
}

由于您只是读取根元素,您甚至可以从 XmlReader 中进行反序列化。而不必重置 FileStream 上的位置.

这避免了两次加载整个文件的开销(一次用于 XmlDocument,然后再次用于 XmlSerializer)- 特别是避免了为每个文档创建 DOM 的内存开销。

一个更核的选择是实现 IXmlSerializable在一组自定义类上,这些类将在 ReadXml 中具有自定义逻辑解析版本属性并实例化正确子类型的方法 - 例如一个CarCollection具有 List<Car> 的类属性(property),在哪里Car是一个具有 CarV1 的抽象类和 CarV2作为后代。这将尽可能高效(并提供对类层次结构设计的非常细粒度的控制),但会消除使用 xsd.exe 生成类的可能性。

关于c# - 确定类如何使用反序列化 XML 的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42137447/

相关文章:

c# - Linq except 多个类属性

c# - 可空类型的静态成员

c# - 在 C# 中使用后期绑定(bind)获取特定的 Excel 实例

xml - 谷歌表格: =importxml is not loading some results

java - 用Java解析包含XML片段的文件

c# - T 必须逆变有效

c# - 名称在注释中使用 cref 时包含无效字符

javascript - Jquery的表单序列化发送重复信息

c# - 通过 TCP 发送大对象 : "End of Stream encountered before parsing was completed"

c++ - 使用 istream_iterator 构建自定义类型的 vector