【C#编程最佳实践 四】XML配置文件编写与读取实践

来源:互联网 发布:matlab find(矩阵) 编辑:程序博客网 时间:2024/06/06 01:44

通过项目获取的新技能,之后写xml配置应该没什么问题,当然xml文件的使用形式多种多样,之后在持续更新。

配置文件编写实践

配置文件一般用xml来写,具体关于xml文件的特性见以下这篇引用的博客,很详细了。

xml文件的使用http://blog.csdn.net/wuya_meiya/article/details/50989600

这里我想说一下我学到的设计

xml文件编写

<?xml version="1.0" encoding="utf-8" ?><CheckMetaDataConfig majorVersion="1" minorVersion="208"    //根节点<DataBases>  <DataBase Name="User">    <TableConfigs>      <TableConfig Name="dbo.userconfig"  ConditionCode="ID,Lable,Name">  //ConditonCode为配置的组合特征,之后需要取出来切割并调用        <Fields>          <Field Name="ID"  Method="Mapping" Field>   //method为我们的比较规则          <Field Name="Lable"  Method="Equal"></Field>          <Field Name="Name"  Method="TenanatReplace"></Field>          <Field Name="Application"  Method="Equal"></Field>        </Fields>      </TableConfig>    </TableConfigs>  </DataBase></DataBases></CheckMetaDataConfig>

以上的结构为,一系列的库,一系列的表,一系列的字段,每一级都可以有很多个,每个又可以有自己的属性。为了对应xml,我们需要解析,还要考虑到我们会通过库来调用表,通过表来调用字段

解析xml文件的类的编写

using User.Configuration;using System;using System.Collections.Generic;using System.Xml.Serialization;namespace User{    //=============================对应根节点的类==========================================    #region 对应根节点的类    /// <summary>    /// 类:对应根节点的类    /// </summary>    [XmlRoot("CheckMetaDataConfig")]    public class CheckMetaDataConfig : BaseConfig<CheckMetaDataConfig>    {        private static readonly object LockThis = new object(); //获取锁对象        //=============================================属性部分====================================        [XmlArray("DataBases")]        [XmlArrayItem("DataBase")]        public DataBase[] DataBases { get; set; }        //=============================================字段部分====================================        private Dictionary<string, DataBase> _databasedic; //设置字段的字典类        //=============================================方法部分====================================        /// <summary>        /// 公有方法:获取指定名称数据库的xml实例        /// </summary>        /// <param name="dataBaseName"></param>        /// <returns></returns>        public DataBase FindDatabase(string dataBaseName)        {            dataBaseName = dataBaseName.ToLower();            if (_databasedic == null)            {                InitDatabaseDic();            }            return _databasedic != null && _databasedic.ContainsKey(dataBaseName) ? _databasedic[dataBaseName] : null;        }        /// <summary>        /// 私有方法:初始化数据库        /// </summary>        private void InitDatabaseDic()        {            lock (LockThis)            {                if (_databasedic == null) //如果字典为null,则初始化字典类                {                    var dic = new Dictionary<String, DataBase>(); //新建一个字典类                    foreach (var app in Instance.DataBases) //遍历该数据库                    {                        app.Name = app.Name.ToLower(); //将数据库名全部转为大写                        if (string.IsNullOrEmpty(app.Name)) continue; //如果该配置文件里的数据库名字存在,则中止,进入下一个                        if (!dic.ContainsKey(app.Name)) //如果字段名字典里不包括该实例里的数据库的名字,添加进去                        {                            dic.Add(app.Name, app); //把数据库名字和数据库实例以字典对的形式添加进去                        }                    }                    _databasedic = dic; //把处理好的dic赋给字典,全新的字典诞生                }            }        }    }}#endregion 对应根节点的类//=============================对应数据库节点的类==========================================#region 对应数据库节点的类/// <summary>/// 类:数据库节点类/// </summary>public class DataBase{    private static readonly object LockThis = new object(); //获取锁对象    //=============================================属性部分====================================    [XmlAttribute("Name")]    public string Name { get; set; }    [XmlArray("TableConfigs")]    [XmlArrayItem("TableConfig")]    public TableConfig[] TableConfigs { get; set; }    //=============================================字段部分====================================    private Dictionary<string, TableConfig> _tableDic;    //=============================================方法部分====================================    /// <summary>    ///公有方法: 获取指定名称的数据表    /// </summary>    /// <param name="tableName"></param>    /// <returns></returns>    public TableConfig FindTable(string tableName)    {        tableName = tableName.ToLower();        if (_tableDic == null)        {            InitTableDic();        }        return _tableDic != null && _tableDic.ContainsKey(tableName) ? _tableDic[tableName] : null;    }    /// <summary>    /// 私有方法:初始化数据表的信息    /// </summary>    private void InitTableDic()    {        lock (LockThis)        {            if (_tableDic == null) //如果字典为null,则初始化字典类            {                var dic = new Dictionary<String, TableConfig>(); //新建一个字典类                foreach (var app in TableConfigs) //遍历该表集合                {                    app.Name = app.Name.ToLower(); //将数据表名全部转为大写                    if (string.IsNullOrEmpty(app.Name)) continue; //如果该配置文件里的数据库名字存在,则中止,进入下一个                    if (!dic.ContainsKey(app.Name)) //如果字段名字典里不包括该实例里的数据表的名字,添加进去                    {                        dic.Add(app.Name, app); //把数据表名字和数据表实例以字典对的形式添加进去                    }                }                _tableDic = dic; //把处理好的dic赋给字典,全新的字典诞生            }        }    }}#endregion 对应数据库节点的类//=============================对应数据表节点的类==========================================#region 对应数据表节点的类/// <summary>/// 类:数据表节点类/// </summary>public class TableConfig{    private static readonly object LockThis = new object(); //获取锁对象    //=============================================属性部分====================================    [XmlAttribute("Name")]    public string Name { get; set; }    [XmlAttribute("ConditionCode")]    public string ConditionCode { get; set; }    [XmlArray("Fields")]    [XmlArrayItem("Field")]    public Field[] Fields { get; set; }    //=============================================字段部分====================================    private Dictionary<String, string> _conditionCodDic;    //=============================================方法部分====================================    /// <summary>    /// 公有方法:获取特征码    /// </summary>    /// <returns></returns>    public Dictionary<String, string> GetConditionCodeDic()    {        if (_conditionCodDic == null)        {            InitConditionCodeDic();        }        return _conditionCodDic;    }    /// <summary>    /// 私有方法: 初始化特征码    /// </summary>    private void InitConditionCodeDic()    {        lock (LockThis)        {            if (_conditionCodDic == null) //如果字典为null,则初始化字典类            {                var dic = new Dictionary<string, string>(); //新建一个字典类                var strs = ConditionCode.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);                //不保留空元素,获取到特征值字段集合                foreach (var s in strs)                {                    dic.Add(s, null);                }                _conditionCodDic = dic; //把处理好的dic赋给字典,全新的字典诞生            }        }    }}#endregion 对应数据表节点的类//=============================对应字段节点的类==========================================#region 对应字段节点的类/// <summary>/// 类: 字段类/// </summary>public class Field{    //=============================================属性部分====================================    [XmlAttribute("Name")]    public string Name { get; set; }    [XmlAttribute("Method")]    public string Method { get; set; }}#endregion 对应字段节点的类

以上代码类似InitTableDic用到的初始化方式可以大大减少访问次数,如果存在就不需要再次获取

调用xml文件类

var dataDaseConfig = CheckMetaDataConfig.Instance.FindDatabase(MetaDataBaseName);  //获取一个配置文件中数据库节点实例

踩过的坑

1,xml解析类编写的时候,字典类的访问修饰符必须是private:private Dictionary<String, string> _conditionCodDic;
2,xml解析类尽量不要出现子类,要写为同级的