反序列化的性能(Deserialization Performance)

反序列化xml配置文件到一个实体类,和直接读取xml到实体类相比,效率对比相当大,我简单测试了一下,各自占用的时间如下:

DeserializationPerformance

部分测试代码:

class Program
{
    static void Main ( string[] args )
    {
        System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch ();
 
        sw1.Start ();
        Config cfg = LoadConfig_Xml ( "MyTest.config" );
        sw1.Stop ();
 
        if ( cfg != null )
            Console.WriteLine ( "NormalReader: " + sw1.ElapsedMilliseconds + " ms" );
        
        sw1.Reset ();
                  
        sw1.Start ();
        cfg = LoadConfig_Deserialize ( "MyTest.config" );
        sw1.Stop ();
 
        if ( cfg != null )
            Console.WriteLine ( "Deserialize: " + sw1.ElapsedMilliseconds + " ms" );
        
        Console.Read ();
    }
            
    public static Config LoadConfig_Deserialize ( string file )
    {
        if ( !System.IO.File.Exists ( file ) ) return null;
 
        XmlSerializer xs = new XmlSerializer ( typeof ( Config ) );
        using ( StreamReader sr = new StreamReader ( file ) )
        {
            return xs.Deserialize ( sr ) as Config;
        }
    }
 
  
    public static Config LoadConfig_Xml ( string file )
    {
        if ( !System.IO.File.Exists ( file ) ) return null;
 
        try
        {
            XmlDocument doc = new XmlDocument ();
 
            doc.Load ( file );
 
            if ( doc == null ) return null;
 
            XmlNode parent = doc.SelectSingleNode ( @"//Config" );
            if ( parent == null ) return null;
 
            Config cfg = new Config ();
 
            foreach ( XmlNode node in parent.ChildNodes )
            {
                if ( node.Name == "MyBooleanAttribute1" )
                    cfg.MyBooleanAttribute1 = Convert.ToBoolean ( node.InnerText );
 
                if ( node.Name == "MyAttribute2" )
                    cfg.MyAttribute2 = node.InnerText;
 
                if ( node.Name == "MyBooleanAttribute3" )
                    cfg.MyBooleanAttribute3 = Convert.ToBoolean ( node.InnerText );
 
                if ( node.Name == "CachedFileList" )
                {
                    if ( node.ChildNodes.Count > 0 )
                    {
                        cfg.CachedFileList = new CachedFileList ();
                        foreach ( XmlNode child in node.ChildNodes )
                        {
                            cfg.CachedFileList.Add ( new CachedFile ( child.Attributes["FileLocation"].InnerText,
                                child.Attributes["FileName"].InnerText, child.Attributes["FileFormat"].InnerText, 
                                Convert.ToInt64 ( child.Attributes["FileChecksum"].InnerText ) ) );
                        }
                    }
                }
            }
            return cfg;
        }
        catch { return null; }
    }
           
}

Config类定义:

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
 
[Serializable]
public class Config
{
    private bool myBooleanAttribute1 = true;
 
   
    public bool MyBooleanAttribute1 { get { return myBooleanAttribute1; } set { myBooleanAttribute1 = value; } }
 
    private string myAttribute2 = "";
 
   
    public string MyAttribute2 { get { return myAttribute2; } set { myAttribute2 = value; } }
 
    private bool myBooleanAttribute3 = true;
 
 
    public bool MyBooleanAttribute3 { get { return myBooleanAttribute3; } set { myBooleanAttribute3 = value; } }
 
    private CachedFileList cachedFileList = new CachedFileList ();
 
  
    public CachedFileList CachedFileList
    {
        get { return cachedFileList; }
        set { cachedFileList = value; }
    }
}
 
[Serializable]
public class CachedFileList : List<CachedFile>
{
}
 
public class CachedFile
{
    private string fileLocation = "";
    private string fileName = "";
    private string fileFormat = "";
    private long fileChecksum = 0;
 
    [XmlAttribute ( "FileLocation" )]
    public string FileLocation { get { return fileLocation; } set { fileLocation = value; } }
 
    [XmlAttribute ( "FileName" )]
    public string FileName { get { return fileName; } set { fileName = value; } }
 
    [XmlAttribute ( "FileFormat" )]
    public string FileFormat { get { return fileFormat; } set { fileFormat = value; } }
 
    [XmlAttribute ( "FileChecksum" )]
    public long FileChecksum { get { return fileChecksum; } set { fileChecksum = value; } }
 
    public CachedFile ( string location, string name, string format, long checksum )
        :this()
    {
        this.fileLocation = location;
        this.fileName = name;
        this.fileFormat = format;
        this.fileChecksum = checksum;
    }
 
    public CachedFile ()
    {
    }
 
}

由此可见,反序列化的性能很差,占用时间非常大。在简洁代码的背后是效率的代价。应该根据需要按需选择。

使用XSD安全装载XML并反序列化

如果有XML Schema,就是XSD的情况下,可以首先装载XSD,然后读取XML会比较快;尤其是读取大型XML文件(比如几M)。而且类型安全。

最后再反序列化到实体类。以下是一个例子:

private XmlReader GetValidatingReader(string filePath)
{
    Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MySchema.xsd");
    XmlTextReader schemaReader = new XmlTextReader(stream);
    stream.Dispose();
 
    XmlReaderSettings settings = new XmlReaderSettings();
    settings.Schemas.Add("http://schemas.microsoft.com/pag/mynamespacefile", schemaReader);
    XmlReader settingReader = XmlReader.Create(filePath, settings);
 
    return settingReader;
}
 
private Config ReadConfig (string configPath)
{
    try
    {
        XmlSerializer serializer = new XmlSerializer ( typeof ( Config ) );
        using ( XmlReader reader = GetValidatingReader () )
        {
           return (Config)serializer.Deserialize ( reader );
        }
    }
    catch ( Exception ex )
    {
        throw new ConfigReaderException ( String.Format (
                                         CultureInfo.CurrentCulture,
                                         Resources.ErrorReadingConfig,
                                         configPath ), ex );
    }
}

Links:

Dataset的序列化传输,压缩和反序列化

如何由XSD自动生成XML和实体类

[转]使用XMLSerializer类持久化数据

原文地址:https://www.cnblogs.com/Mainz/p/1155722.html