Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 确定类如何反序列化XML的最有效方法_C#_Xml_Serialization_Xsd - Fatal编程技术网

C# 确定类如何反序列化XML的最有效方法

C# 确定类如何反序列化XML的最有效方法,c#,xml,serialization,xsd,C#,Xml,Serialization,Xsd,我有许多xml模式的.xsd文件 范例 xml1.0-XML\u 1\u 0.XML <?xml version="1.0" encoding="UTF-8"?> <cars version="1.00"> <car>Honda</car> <car>Ferrari</car> </cars> <?xml version="1.0" encoding

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

范例

xml1.0-XML\u 1\u 0.XML

<?xml version="1.0" encoding="UTF-8"?>
     <cars version="1.00">
         <car>Honda</car>
         <car>Ferrari</car>
     </cars>
<?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>
然后像这样反序列化:

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
进行反序列化,而不必重置
文件流上的位置

这避免了两次加载整个文件的开销(一次用于
XmlDocument
,另一次用于
XmlSerializer
),尤其避免了为每个文档创建DOM的内存开销


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

您可以共享实际的xsd吗?修改XSD是一个选项吗?创建一个新类是一种选择吗?在我编写的问题中,仅举一个例子,xsd文件要复杂得多,任何版本的xml都有许多其他属性
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);

        }
    }
}