c#正反序列化XML文件示例(xml序列化)

 更新时间:2014年03月04日 16:38:07   作者:  
这篇文章主要介绍了c#正反序列化XML文件示例,可以将对象序列化为XML文本或者文件,或者将XML文件或文本反序列化为对象,要求进行序列化的对象不能出现序列化异常,支持类的嵌套,要求类的属性为public

复制代码 代码如下:

using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using System.IO;
using System;

namespace GlobalTimes.Framework
{
    /// <summary>
    /// XML文本通用解释器
    /// </summary>
    public class XmlHelper
    {
        private const string EncodePattern = "<[^>]+?encoding=\"(?<enc>[^<>\\s]+)\"[^>]*?>";
        private static readonly Encoding DefEncoding = Encoding.GetEncoding("gb2312");
        private static readonly Regex RegRoot = new Regex("<(\\w+?)[ >]", RegexOptions.Compiled);
        private static readonly Regex RegEncode = new Regex(EncodePattern,
                                                            RegexOptions.Compiled | RegexOptions.IgnoreCase);
        private static readonly Dictionary<string, XmlSerializer> Parsers = new Dictionary<string, XmlSerializer>();
        #region 解析器

        static Encoding GetEncoding(string input)
        {
            var match = RegEncode.Match(input);
            if (match.Success)
            {
                try
                {
                    return Encoding.GetEncoding(match.Result("${enc}"));
                }
// ReSharper disable EmptyGeneralCatchClause
                catch (Exception)
// ReSharper restore EmptyGeneralCatchClause
                {
                }
            }
            return DefEncoding;
        }

        /// <summary>
        /// 解析XML文件
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="fileName">文件名</param>
        /// <returns>类的实例</returns>
        public T ParseFile<T>(string fileName) where T : class, new()
        {
            var info = new FileInfo(fileName);
            if (!info.Extension.Equals(".xml", StringComparison.CurrentCultureIgnoreCase) || !info.Exists)
            {
                throw new ArgumentException("输入的文件名有误!");
            }
            string body;
            var tempFileName = PathHelper.PathOf("temp", Guid.NewGuid().ToString().Replace("-", "") + ".xml");
            var fi = new FileInfo(tempFileName);
            var di = fi.Directory;
            if (di != null && !di.Exists)
            {
                di.Create();
            }
            File.Copy(fileName, tempFileName);
            using (Stream stream = File.Open(tempFileName, FileMode.Open, FileAccess.Read))
            {
                using (TextReader reader = new StreamReader(stream, DefEncoding))
                {
                    body = reader.ReadToEnd();
                }
            }
            File.Delete(tempFileName);
            var enc = GetEncoding(body);
            if (!Equals(enc, DefEncoding))
            {
                var data = DefEncoding.GetBytes(body);
                var dest = Encoding.Convert(DefEncoding, enc, data);
                body = enc.GetString(dest);
            }
            return Parse<T>(body, enc);
        }

        /// <summary>
        /// 将对象序列化为XML文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">文件名错误异常</exception>
        public bool SaveFile(string fileName, object obj)
        {
            return SaveFile(fileName, obj, DefEncoding);
        }

        /// <summary>
        /// 将对象序列化为XML文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="obj">对象</param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">文件名错误异常</exception>
        public bool SaveFile(string fileName, object obj,Encoding encoding)
        {
            var info = new FileInfo(fileName);
            if (!info.Extension.Equals(".xml", StringComparison.CurrentCultureIgnoreCase))
            {
                throw new ArgumentException("输入的文件名有误!");
            }
            if (obj == null) return false;
            var type = obj.GetType();
            var serializer = GetSerializer(type);

            using (Stream stream = File.Open(fileName, FileMode.Create, FileAccess.Write))
            {
                using (TextWriter writer = new StreamWriter(stream, encoding))
                {
                    serializer.Serialize(writer, obj);
                }
            }
            return true;
        }
        static XmlSerializer GetSerializer(Type type)
        {
            var key = type.FullName;
            XmlSerializer serializer;
            var incl = Parsers.TryGetValue(key, out serializer);
            if (!incl || serializer == null)
            {
                var rootAttrs = new XmlAttributes { XmlRoot = new XmlRootAttribute(type.Name) };
                var attrOvrs = new XmlAttributeOverrides();
                attrOvrs.Add(type, rootAttrs);
                try
                {
                    serializer = new XmlSerializer(type, attrOvrs);
                }
                catch (Exception e)
                {
                    throw new Exception("类型声明错误!" + e);
                }
                Parsers[key] = serializer;
            }
            return serializer;
        }
        /// <summary>
        /// 解析文本
        /// </summary>
        /// <typeparam name="T">需要解析的类</typeparam>
        /// <param name="body">待解析文本</param>
        /// <returns>类的实例</returns>
        public T Parse<T>(string body) where T : class, new()
        {
            var encoding = GetEncoding(body);
            return Parse<T>(body, encoding);
        }

        /// <summary>
        /// 解析文本
        /// </summary>
        /// <typeparam name="T">需要解析的类</typeparam>
        /// <param name="body">待解析文本</param>
        /// <param name="encoding"></param>
        /// <returns>类的实例</returns>
        public T Parse<T>(string body, Encoding encoding) where T : class, new()
        {
            var type = typeof (T);
            var rootTagName = GetRootElement(body);

            var key = type.FullName;
            if (!key.Contains(rootTagName))
            {
                throw new ArgumentException("输入文本有误!key:" + key + "\t\troot:" + rootTagName);
            }

            var serializer = GetSerializer(type);
            object obj;
            using (Stream stream = new MemoryStream(encoding.GetBytes(body)))
            {
                obj = serializer.Deserialize(stream);
            }
            if (obj == null) return null;
            try
            {
                var rsp = (T) obj;
                return rsp;
            }
            catch (InvalidCastException)
            {
                var rsp = new T();
                var pisr = typeof (T).GetProperties();
                var piso = obj.GetType().GetProperties();
                foreach (var info in pisr)
                {
                    var info1 = info;
                    foreach (var value in from propertyInfo in piso where info1.Name.Equals(propertyInfo.Name) select propertyInfo.GetValue(obj, null))
                    {
                        info.SetValue(rsp, value, null);
                        break;
                    }
                }
                return rsp;
            }
        }

        private static XmlSerializer BuildSerializer(Type type)
        {
            var rootAttrs = new XmlAttributes { XmlRoot = new XmlRootAttribute(type.Name) };
            var attrOvrs = new XmlAttributeOverrides();
            attrOvrs.Add(type, rootAttrs);
            try
            {
                return new XmlSerializer(type, attrOvrs);
            }
            catch (Exception e)
            {
                throw new Exception("类型声明错误!" + e);
            }
        }

        /// <summary>
        /// 解析未知类型的XML内容
        /// </summary>
        /// <param name="body">Xml文本</param>
        /// <param name="encoding">字符编码</param>
        /// <returns></returns>
        public object ParseUnknown(string body, Encoding encoding)
        {
            var rootTagName = GetRootElement(body);
            var array = AppDomain.CurrentDomain.GetAssemblies();
            Type type = null;
            foreach (var assembly in array)
            {
                type = assembly.GetType(rootTagName, false, true);
                if (type != null) break;
            }
            if (type == null)
            {
                Logger.GetInstance().Warn("加载 {0} XML类型失败! ", rootTagName);
                return null;
            }
            var serializer = GetSerializer(type);
            object obj;
            using (Stream stream = new MemoryStream(encoding.GetBytes(body)))
            {
                obj = serializer.Deserialize(stream);
            }

            var rsp = obj;
            return rsp;
        }
        /// <summary>
        /// 用XML序列化对象
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public string Serialize(object obj)
        {
            if (obj == null) return string.Empty;
            var type = obj.GetType();
            var serializer = GetSerializer(type);
            var builder = new StringBuilder();
            using (TextWriter writer = new StringWriter(builder))
            {
                serializer.Serialize(writer, obj);
            }
            return builder.ToString();
        }
        #endregion

        /// <summary>
        /// 获取XML响应的根节点名称
        /// </summary>
        private static string GetRootElement(string body)
        {
            var match = RegRoot.Match(body);
            if (match.Success)
            {
                return match.Groups[1].ToString();
            }
            throw new Exception("Invalid XML format!");
        }

    }
}

相关文章

  • C#实现Json文件读写的方法代码

    C#实现Json文件读写的方法代码

    这篇文章主要给大家介绍了关于C#实现Json文件读写的相关资料,C# 读取JSON文件并读取某一个关键字的值可以使用Newtonsoft.Json库,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • 在C#中如何使用Dapper详解(译)

    在C#中如何使用Dapper详解(译)

    这篇文章主要给大家介绍了关于在C#中如何使用Dapper的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起看看吧
    2018-09-09
  • 利用TaskManager爬取2万条代理IP实现自动投票功能

    利用TaskManager爬取2万条代理IP实现自动投票功能

    话说某天心血来潮想到一个问题,朋友圈里面经常有人发投票链接,让帮忙给XX投票,以前呢会很自觉打开链接帮忙投一票。可是这种事做多了就会考虑能不能使用工具来进行投票呢,身为一名程序猿决定研究解决这个问题。感兴趣的朋友一起学习吧
    2015-09-09
  • c#实现的操作oracle通用类

    c#实现的操作oracle通用类

    这篇文章主要介绍了c#实现的操作oracle通用类,用来操作oracle数据库十分的方便,需要的朋友可以参考下
    2014-08-08
  • C#实现控制摄像头的类

    C#实现控制摄像头的类

    这篇文章主要介绍了C#实现控制摄像头的类,涉及C#操作摄像头的初始化、抓图、录像等功能,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-09-09
  • 事务在c#中的使用

    事务在c#中的使用

    这篇文章介绍了事务在c#中的使用,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • Unity3D实现待机状态图片循环淡入淡出

    Unity3D实现待机状态图片循环淡入淡出

    这篇文章主要为大家详细介绍了Unity3D实现待机状态图片循环淡入淡出,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • C#实现文件与字符串互转的方法详解

    C#实现文件与字符串互转的方法详解

    这篇文章主要为大家详细介绍了如何利用C#实现文件与字符串互转效果,文中的示例代码讲解详细,对我们学习C#有一定帮助,需要的可以参考一下
    2022-08-08
  • C#使用TimeSpan对象实现获取时间间隔

    C#使用TimeSpan对象实现获取时间间隔

    TimeSpan对象代表两个时间段的间隔或跨度,使用TimeSpan对象可以方便地获取两个时间段的间隔,下面我们就来看看C#使用TimeSpan对象实现获取时间间隔的具体操作吧
    2024-01-01
  • 基于C#编写一个接受图片流的OCR识别接口

    基于C#编写一个接受图片流的OCR识别接口

    这篇文章主要为大家详细介绍了如何使用C#写一个接受图片流的OCR识别接口,以及测试用例调用接口,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-03-03

最新评论