You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 lines
9.5 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
namespace Utils.Files
{
/// <summary>
/// 通过XML文件保存配置信息;读取通过XML文件保存配置信息
/// <para>只处理两级信息:根、根的下一级。如果有更多级,则读取的信息将会出错</para>
/// </summary>
/// <typeparam name="T">配置数据保存在类型为T的对象中</typeparam>
public class XmlConfig<T>
{
/// <summary>
/// 通过XML文件设置配置信息
/// </summary>
/// <param name="fileName_pathAndFileName">文件名(程序所在目录)或路径+文件名</param>
/// <param name="setting">配置信息</param>
public static void SetConfig(string fileName_pathAndFileName, T setting)
{
XmlSerializer ser = new XmlSerializer(typeof(T));
TextWriter wr = new StreamWriter(fileName_pathAndFileName);
ser.Serialize(wr, setting);
wr.Close();
}
/// <summary>
/// 获取所有配置信息。只包含两级信息,即:根、根的下一级
/// </summary>
/// <param name="fileName_pathAndFileName">文件名(程序所在目录)或路径+文件名</param>
public static Dictionary<string, string> GetAllConfigs(string fileName_pathAndFileName)
{
XmlDocument xmlDoc = Load(fileName_pathAndFileName);
return GetAllConfigs(xmlDoc);
}
/// <summary>
/// 获取所有配置信息。只包含两级信息,即:根、根的下一级
/// </summary>
/// <param name="xmlDoc">读取出的xml文档信息</param>
public static Dictionary<string, string> GetAllConfigs(XmlDocument xmlDoc)
{
XmlNode rootNode = xmlDoc.ChildNodes[1];//根节点
return findChild(rootNode, true);
}
/// <summary>
/// 向配置文件中增加配置信息。如果已存在,则为修改配置信息
/// </summary>
/// <param name="fileName_pathAndFileName">配置文件的文件名</param>
/// <param name="name">配置信息的名字</param>
/// <param name="value">配置信息的内容</param>
public static void AddConfig(string fileName_pathAndFileName, string name, string value)
{
XmlDocument xmlDoc = Load(fileName_pathAndFileName);
var configs = GetAllConfigs(xmlDoc);
AddOrChange(xmlDoc, configs, name, value);
xmlDoc.Save(fileName_pathAndFileName);
}
/// <summary>
/// 向配置文件中增加配置信息。如果已存在,则为修改配置信息
/// </summary>
/// <param name="fileName_pathAndFileName">配置文件的文件名</param>
/// <param name="configs">配置信息。key为名字,value为内容</param>
public static void AddConfig(string fileName_pathAndFileName, Dictionary<string, string> configs)
{
XmlDocument xmlDoc = Load(fileName_pathAndFileName);
var oldConfigs = GetAllConfigs(xmlDoc);
foreach (var config in configs) {
AddOrChange(xmlDoc, oldConfigs, config.Key, config.Value);
}
xmlDoc.Save(fileName_pathAndFileName);
}
/// <summary>
/// 获取指定的配置。没有则返回null
/// </summary>
/// <param name="fileName_pathAndFileName">文件名(程序所在目录)或路径+文件名</param>
/// <param name="name">要获取的配置的名称</param>
public static string GetConfig(string fileName_pathAndFileName, string name)
{
if (GetAllConfigs(fileName_pathAndFileName).Keys.Contains(name))
return GetAllConfigs(fileName_pathAndFileName)[name];
return null;
}
/// <summary>
/// 获取指定的配置,结果为字符串数组。没有则返回空数组,即:{}
/// </summary>
/// <param name="fileName_pathAndFileName">文件名(程序所在目录)或路径+文件名</param>
/// <param name="name">要获取的配置的名称</param>
/// <param name="values">配置内容</param>
public static void GetConfig(string fileName_pathAndFileName, string name, out string[] values)
{
var valuesArr = GetConfig(fileName_pathAndFileName, name);
if (!string.IsNullOrEmpty(valuesArr))
values = valuesArr.Split(',');
else
values = new string[] { };
}
private static Dictionary<string, string> findChild(XmlNode rootNode, bool includeEmpty)
{
Dictionary<string, string> reslut = new Dictionary<string, string>();
XmlNodeList list = rootNode.ChildNodes;
if (list == null || list.Count == 0)
return reslut;
foreach (XmlNode node in list) {
if (node.HasChildNodes && node.ChildNodes.Count > 0) {
if (node.ChildNodes.Count == 1 && node.FirstChild.NodeType == XmlNodeType.Text) {
reslut.Add(node.Name, node.InnerText);
} else {
throw new ApplicationException("配置不正确");
}
} else {
if (includeEmpty)
reslut.Add(node.Name, node.InnerText);
}
}
return reslut;
}
/// <summary>
/// 从配置文件中读取信息。成功则返回true,并返回代表该配置文件的对象;文件不存在则返回false。
/// </summary>
/// <param name="fileName_pathAndFileName">配置文件的名称或路径名称</param>
/// <param name="xmlDoc">代表读取出来的文件的对象</param>
/// <returns>成功则返回true,并返回代表该配置文件的对象;文件不存在则返回false。</returns>
protected static bool Load(string fileName_pathAndFileName, out XmlDocument xmlDoc)
{
xmlDoc = new XmlDocument();
try {
xmlDoc.Load(fileName_pathAndFileName);
} catch (FileNotFoundException) {
return false;
}
return true;
}
/// <summary>
/// 获取代表配置文件的对象。如果不存在,则创建空配置文件,并返回代表该配置文件的对象。
/// </summary>
/// <param name="fileName_pathAndFileName">文件名</param>
protected static XmlDocument Load(string fileName_pathAndFileName)
{
XmlDocument xmlDoc;
if (!Load(fileName_pathAndFileName, out xmlDoc)) {//当文件不存在时
Configs setting = new Configs();
XmlConfig<Configs>.SetConfig(fileName_pathAndFileName, setting);
Load(fileName_pathAndFileName, out xmlDoc);
}
return xmlDoc;
}
/// <summary>
/// 添加或修改配置信息。添加、修改取决于name是否存在
/// <para>要使修改生效,还需要在调用该方法后,进行保存操作</para>
/// </summary>
/// <param name="xmlDoc">代表配置文件的对象</param>
/// <param name="configs">从配置文件中读取出来的配置信息(用于方法内的查询)</param>
/// <param name="name">配置名字</param>
/// <param name="value">配置对应的值</param>
private static void AddOrChange(XmlDocument xmlDoc, Dictionary<string, string> configs, string name, string value)
{
if (configs.Keys.Contains(name))
foreach (XmlNode node in xmlDoc.ChildNodes[1].ChildNodes) {
if (node.Name == name) {
node.InnerText = value;
return;
}
}
XmlNode rootNode = xmlDoc.ChildNodes[1];//根节点
XmlElement element = xmlDoc.CreateElement(name);
element.InnerText = value;
rootNode.AppendChild(element);
}
}
#region
public struct Configs//空结构,用于创建配置信息为空的配置文件(并不是什么信息都没有)
{
}
public class XmlConfig : XmlConfig<Configs>
{
public static Dictionary<string, TrinaryValue> GetAllSystemConfigs(string fileName_pathAndFileName)
{
XmlDocument xmlDoc;
return GetAllSystemConfigs(fileName_pathAndFileName, out xmlDoc);
}
private static Dictionary<string, TrinaryValue> GetAllSystemConfigs(string fileName_pathAndFileName, out XmlDocument xmlDoc)
{
Dictionary<string, TrinaryValue> result = new Dictionary<string, TrinaryValue>();
//XmlDocument xmlDoc;
if (Load(fileName_pathAndFileName, out xmlDoc)) {
XmlNodeList list = xmlDoc.ChildNodes[1].ChildNodes;
if (list == null || list.Count == 0)
return new Dictionary<string, TrinaryValue>();
foreach (XmlNode node in list) {
if (node.Attributes.Count > 0) {
TrinaryValue value = new TrinaryValue();
foreach (XmlAttribute attr in node.Attributes) {
switch (attr.Name) {
case "Name":
value.Key = attr.Value;
break;
case "DisplayName":
value.DisplayName = attr.Value;
break;
case "WebRoot":
value.Value = attr.Value;
break;
default:
break;
}
}
if (value.Key.Length > 0)
result.Add(value.Key, value);
}
}
}
return result;
}
public static void AddConfig(string fileName_pathAndFileName, TrinaryValue attributeValue)
{
XmlDocument xmlDoc;
var configs = GetAllSystemConfigs(fileName_pathAndFileName, out xmlDoc);
if (!configs.Keys.Contains(attributeValue.Key))
throw new ApplicationException("错误!\n要修改的项不存在!\n这个错误不应出现");
bool hasChanged = false;
foreach (XmlNode node in xmlDoc.ChildNodes[1].ChildNodes) {
if (hasChanged)
break;
foreach (XmlAttribute attr in node.Attributes) {
if (attr.Name == "Name" && attr.Value == attributeValue.Key) {
ChangeAttribute(node, attributeValue);
hasChanged = true;
}
}
}
xmlDoc.Save(fileName_pathAndFileName);
}
private static void ChangeAttribute(XmlNode node, TrinaryValue attributeValue)
{
foreach (XmlAttribute attr in node.Attributes) {
switch (attr.Name) {
case "DisplayName":
attr.Value = attributeValue.DisplayName;
break;
case "WebRoot":
attr.Value = attributeValue.Value;
break;
default:
break;
}
}
}
}
public struct TrinaryValue
{
public string Key { get; set; }
public string DisplayName { get; set; }
public string Value { get; set; }
}
#endregion
}