在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>即可。