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

所属分类: 软件编程 / C#教程 阅读数: 115
收藏 0 赞 0 分享

复制代码 代码如下:

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#开发word批量转pdf源码分享

已经安装有Office环境,借助一些简单的代码即可实现批量Word转PDF,看下面的实例源码吧
收藏 0 赞 0 分享

c# xml API操作的小例子

这篇文章主要介绍了c# xml API操作的小例子,有需要的朋友可以参考一下
收藏 0 赞 0 分享

c#唯一值渲染实例代码

这篇文章主要介绍了c#唯一值渲染实例代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

淘宝IP地址库采集器c#代码

这篇文章主要介绍了淘宝IP地址库采集器c#代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

C#在后台运行操作(BackgroundWorker用法)示例分享

BackgroundWorker类允许在单独的专用线程上运行操作。如果需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用BackgroundWorker类方便地解决问题,下面看示例
收藏 0 赞 0 分享

c#文本加密程序代码示例

这是一个加密软件,但只限于文本加密,加了窗口控件的滑动效果,详细看下面的代码
收藏 0 赞 0 分享

c#生成站点地图(SiteMapPath)文件示例程序

这篇文章主要介绍了c#生成站点地图(SiteMapPath)文件的示例,大家参考使用
收藏 0 赞 0 分享

C# 键盘Enter键取代Tab键实现代码

这篇文章主要介绍了C# 键盘Enter键取代Tab键实现代码,有需要的朋友可以参考一下
收藏 0 赞 0 分享

C# WinForm导出Excel方法介绍

在.NET应用中,导出Excel是很常见的需求,导出Excel报表大致有以下三种方式:Office PIA,文件流和NPOI开源库,本文只介绍前两种方式
收藏 0 赞 0 分享

C#串口通信程序实例详解

在.NET平台下创建C#串口通信程序,.NET 2.0提供了串口通信的功能,其命名空间是System.IO.Ports,创建C#串口通信程序的具体实现是如何的呢?让我们开始吧
收藏 0 赞 0 分享
查看更多