在2010年之前,XML是最流行的数据交换标准,直至今天,仍然有许多系统使用XML交换数据。NewLife.Core 很早就提供了XML序列化支持,主要用于配置文件。
Nuget包:NewLife.Core
源码:https://github.com/NewLifeX/X/tree/master/NewLife.Core/Serialization/Xml
视频:https://www.bilibili.com/video/BV1NN4y1P7B8
基本用法
NewLife.Serialization.Xml 类主要成员如下:
/// <summary>深度</summary> public Int32 Depth { get; set; } /// <summary>处理器列表</summary> public List<IXmlHandler> Handlers { get; } /// <summary>使用特性</summary> public Boolean UseAttribute { get; set; } /// <summary>使用注释</summary> public Boolean UseComment { get; set; } /// <summary>当前名称</summary> public String CurrentName { get; set; } // 写入一个对象 Boolean Write(Object value, String name = null, Type type = null); // 读取指定类型对象 Object Read(Type type); T Read<T>(); Boolean TryRead(Type type, ref Object value);
Xml配置文件
Xml至今仍然是很多系统配置文件的优先选择,最主要是因为它支持注释。
先来看一个SysConfig配置类的文件内容:
<?xml version="1.0" encoding="utf-8"?> <Sys> <!--用于标识系统的英文名--> <Name>StarServer</Name> <!--系统版本--> <Version>1.0.7558.41644</Version> <!--用户可见的名称--> <DisplayName>星尘分布式服务</DisplayName> <!--公司--> <Company>新生命开发团队</Company> <!--应用实例。单应用多实例部署时用于唯一标识实例节点--> <Instance>3</Instance> <!--开发者模式--> <Develop>true</Develop> <!--启用--> <Enable>true</Enable> <!--安装时间--> <InstallTime>2020-09-10 23:08:42</InstallTime> </Sys>
它的模型类是这样的:
/// <summary>系统设置。提供系统名称、版本等基本设置</summary> [DisplayName("系统设置")] [XmlConfigFile("config\\sys.config", 15_000)] public class SysConfig : XmlConfig<SysConfig> { #region 属性 /// <summary>系统名称</summary> [DisplayName("系统名称")] [Description("用于标识系统的英文名")] public String Name { get; set; } = ""; /// <summary>系统版本</summary> [DisplayName("系统版本")] public String Version { get; set; } = ""; /// <summary>显示名称</summary> [DisplayName("显示名称")] [Description("用户可见的名称")] public String DisplayName { get; set; } = ""; /// <summary>公司</summary> [DisplayName("公司")] public String Company { get; set; } = ""; /// <summary>应用实例。单应用多实例部署时用于唯一标识实例节点</summary> [DisplayName("应用实例。单应用多实例部署时用于唯一标识实例节点")] public Int32 Instance { get; set; } /// <summary>开发者模式</summary> [DisplayName("开发者模式")] public Boolean Develop { get; set; } = true; /// <summary>启用</summary> [DisplayName("启用")] public Boolean Enable { get; set; } = true; /// <summary>安装时间</summary> [DisplayName("安装时间")] public DateTime InstallTime { get; set; } = DateTime.Now; #endregion }
配置类需要继承 XmlConfig<T> 基类,然后直接通过静态属性Current读写。头部 XmlConfigFile 特性指定配置文件放在 config\sys.config,然后每15秒重新读取一次配置文件,确保SysConfig.Current得到最新的配置信息。
// 读取 var set = SysConfig.Current; var name = set.Name; // 保存 set.DisplayName = "星尘服务"; set.Save();
如果配置文件不存在,会自动创建新文件,并写入默认值;
如果配置文件字段有增减,或者注释内容有改变,下一次读写时自动覆盖;
XmlConfig基类有个 OnLoad 方法可以重载,子类通过重载 OnLoad 可以在每次加载配置文件之后,校验配置数据是否有错漏,并加以修正。
例如魔方配置文件:
/// <summary>加载时触发</summary> protected override void OnLoaded() { #if __CORE__ if (StartPage.IsNullOrEmpty()) StartPage = "/Admin/User/Info"; #else if (StartPage.IsNullOrEmpty()) StartPage = System.Web.HttpRuntime.AppDomainAppVirtualPath.EnsureEnd("/") + "Admin/User/Info"; #endif var web = Runtime.IsWeb; //if (AvatarPath.IsNullOrEmpty()) AvatarPath = web ? "..\\Avatars" : "Avatars"; if (DefaultRole.IsNullOrEmpty() || DefaultRole == "3") DefaultRole = "普通用户"; if (JwtSecret.IsNullOrEmpty() || JwtSecret.Split(':').Length != 2) JwtSecret = $"HS256:{Rand.NextString(16)}"; // 取版权信息 if (Copyright.IsNullOrEmpty()) { var asm = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly(); if (asm != null) { var att = asm.GetCustomAttribute<AssemblyCopyrightAttribute>(); if (att != null) { Copyright = att.Copyright; } } } base.OnLoaded(); }
该代码用于给部分配置属性增加默认值。
IsNew 属性用于判断是否首次新建的配置文件,当配置文件不存在,首次访问需要新建时,IsNew 为 true,其它时候都是false。
总结
当今最流行数据交换格式是Json,几乎没有新系统继续使用Xml作为数据交换。
新的配置系统独立实现了Xml读写,也不再需要这里的Xml序列化,作为兼容,只需要把基类从XmlConfig<T>修改为Config<T>即可。