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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 【C#编程最佳实践 四】XML配置文件编写与读取实践

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

配置文件编写实践

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


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

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解析类尽量不要出现子类,要写为同级的

3,注意xml文件名必须和xml解析类必须同名

相关文章
|
16天前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
29 3
|
1月前
|
XML Java 数据格式
Spring从入门到入土(xml配置文件的基础使用方式)
本文详细介绍了Spring框架中XML配置文件的使用方法,包括读取配置文件、创建带参数的构造对象、使用工厂方法和静态方法创建对象、对象生命周期管理以及单例和多例模式的测试。
85 7
Spring从入门到入土(xml配置文件的基础使用方式)
|
2月前
|
XML JSON 数据处理
C# 中的 XML 与 JSON 数据处理
在现代软件开发中,数据交换和存储需求日益增长,XML 和 JSON 成为最常用的数据格式。本文从 C# 角度出发,详细介绍如何处理这两种格式,并提供示例代码。对于 XML,我们介绍了读取、创建和写入 XML 文件的方法;对于 JSON,则展示了如何使用 Newtonsoft.Json 库进行数据解析和序列化。此外,文章还总结了常见问题及其解决方案,帮助开发者更好地应对实际项目中的挑战。
180 61
C# 中的 XML 与 JSON 数据处理
|
24天前
|
测试技术 C# 数据库
C# 一分钟浅谈:测试驱动开发 (TDD) 实践
【10月更文挑战第18天】测试驱动开发(TDD)是一种软件开发方法论,强调先编写测试代码再编写功能代码,以确保代码质量和可维护性。本文从 TDD 的基本概念入手,详细介绍了其核心步骤——编写测试、运行测试并失败、编写代码使测试通过,以及“红绿重构”循环。文章还探讨了 TDD 的优势,包括提高代码质量、促进设计思考、减少调试时间和文档化。此外,文中分析了常见问题及解决方案,如测试覆盖率不足、测试代码过于复杂、忽视重构和测试依赖过多,并通过一个简单的计算器类的代码案例,展示了 TDD 的实际应用过程。
33 1
|
1月前
|
XML Java 应用服务中间件
tomcat学习一:tomcat 目录及配置文件学习 server.xml 等
这篇文章是关于Apache Tomcat服务器的目录结构、配置文件(特别是server.xml)的详细介绍和学习指南。
58 0
tomcat学习一:tomcat 目录及配置文件学习 server.xml 等
|
1月前
|
存储 JSON API
HTTP 请求与响应处理:C#中的实践
【10月更文挑战第4天】在现代Web开发中,HTTP协议至关重要,无论构建Web应用还是API开发,都需要熟练掌握HTTP请求与响应处理。本文从C#角度出发,介绍HTTP基础知识,包括请求与响应结构,并通过`HttpClient`库演示如何发送GET请求及处理响应,同时分析常见错误并提供解决方案,助你更高效地完成HTTP相关任务。
84 2
|
1月前
|
数据采集 C# 数据库
数据验证与错误处理:C#中的实践
【10月更文挑战第1天】在软件开发中,数据验证与错误处理至关重要,不仅能提升程序的健壮性和安全性,还能改善用户体验。本文从基础概念入手,详细介绍了C#中的数据验证方法,包括使用自定义属性和静态方法验证数据,以及常见的错误处理技巧,如Try-Catch-Finally结构和自定义异常。通过具体示例,帮助读者掌握最佳实践,构建高质量应用。
84 3
|
1月前
|
开发框架 缓存 算法
开源且实用的C#/.NET编程技巧练习宝库(学习,工作,实践干货)
开源且实用的C#/.NET编程技巧练习宝库(学习,工作,实践干货)
|
1月前
|
安全 C# 数据安全/隐私保护
实现C#编程文件夹加锁保护
【10月更文挑战第16天】本文介绍了两种用 C# 实现文件夹保护的方法:一是通过设置文件系统权限,阻止普通用户访问;二是使用加密技术,对文件夹中的文件进行加密,防止未授权访问。提供了示例代码和使用方法,适用于不同安全需求的场景。
105 0
|
2月前
|
API C#
C# 一分钟浅谈:文件系统编程
在软件开发中,文件系统操作至关重要。本文将带你快速掌握C#中文件系统编程的基础知识,涵盖基本概念、常见问题及解决方法。文章详细介绍了`System.IO`命名空间下的关键类库,并通过示例代码展示了路径处理、异常处理、并发访问等技巧,还提供了异步API和流压缩等高级技巧,帮助你写出更健壮的代码。
42 2