自定义配置信息的高级应用

通过上篇博文对简单的自定义配置信息的学习,使得更加灵活的控制系统配置信息。实际项目中,这种配置的灵活度往往无法满足项目的灵活度和扩展性。

比如,一个配置信息有三部分组成,而每部分中有包括一些配置信息。仅仅使用简单的自定义配置无法满足,因此,需要提供更多的自定义配置方法来灵活实现。

针对配置信息中包括配置列表和配置项的要求,主要使用.Net Framework中的以下两个类来实现:

ConfigurationElement:配置文件中的一个配置项

ConfigurationElementCollection:配置文件中的一个配置项集合

ConfigurationSection:配置文件中的一个配置节信息。

使用下面的表格能够更好说明三者之间的关系:

ConfigurationSection

1:N

ConfigurationElementCollection

1:N

ConfigurationElement <add …/>

ConfigurationElement <add …/>

ConfigurationElement <add …/>

针对以上知识点,使用一个项目实例逐渐展开。

项目需求:

库位管理系统需要实现仓库的全方位展示,设计多种数据(SQLserver、Oracle、MySQL等),每个数据库连接字符串的加密方式存在无法统一的情况。

配置文件的规划:

针对以上需求,对数据库配置文件信息的规划为:

DBConnectionConfiguration(ConfigurationSection)

ConnectionStrings(ConfigurationElementCollection)

ConnectionString1(ConfigurationElement)

name

description

connectionString

providerName

connectionDecryptName

ConnectionString2(ConfigurationElement)

name

description

connectionString

providerName

connectionDecryptName

DataProviders(ConfigurationElementCollection)

DataProvider1(ConfigurationElement)

name

description

type

DataProvider2(ConfigurationElement)

name

description

type

ConnectionDecrypts(ConfigurationElementCollection)

ConnectionDecrypt(ConfigurationElement)

name

description

type

ConnectionDecrypt(ConfigurationElement)

name

description

type

配置信息实体的定义:

针对以上配置信息,先对配置信息对应的实体进行设计:

1. DBConnectionConfiguration

它作为配置文件中的一个配置节存在,配置节名称定义为TT.connectionManager,需要继承自ConfigurationSection类,同时,它还需要定义三个属性,分别是ConnectionStrings、DataProviders、ConnectionDecrypts,这三个属性都是列表信息,因此是ConfigurationElementCollection的自定义子类。

     /// <summary>
/// 数据库连接配置信息
/// </summary>
public class DBConnectionConfiguration : ConfigurationSection
{
private const string SECION_NAME = "TT.connectionManager"; /// <summary>
/// 获取数据库连接配置信息
/// </summary>
public static DBConnectionConfiguration GetConfig()
{
var config = ConfigurationManager.GetSection(SECION_NAME) as DBConnectionConfiguration;
return config;
} /// <summary>
/// 数据库连接字符串配置集合
/// </summary>
[ConfigurationProperty("connectionStrings")]
public ConnectionStringCollection ConnectionStrings
{
get
{
return (ConnectionStringCollection)base["connectionStrings"];
}
} /// <summary>
/// DataProvider配置集合
/// </summary>
[ConfigurationProperty("dataProviders", IsRequired = true)]
public DataProviderCollection DataProviders
{
get
{
return (DataProviderCollection)base["dataProviders"];
}
} /// <summary>
/// 连接字符串加密方式
/// </summary>
[ConfigurationProperty("connectionDecrypts", IsRequired = false)]
public ConnectionDecryptCollection ConnectionDecrypts
{
get
{
return (ConnectionDecryptCollection)base["connectionDecrypts"];
}
}
}

2. ConnectionString

由于定义ConfigurationElementCollection的子类时,需要使用泛型方式,定义其包含的配置项的类型,因此,先定义配置项的实体。

由于,三个不同的配置项派生类都需要在配置信息中定义名称和描述信息来标识配置项信息,因此,提取出配置项基类,使用的配置项实体都继承自该基类,不同的配置信息在各自类中进行自定义。

     /// <summary>
/// 以名字为键值的配置项
/// </summary>
public class NamedConfigurationElement : ConfigurationElement
{
/// <summary>
/// 名称
/// </summary>
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
public virtual string Name
{
get
{
return (string)this["name"];
}
} /// <summary>
/// 描述
/// </summary>
[ConfigurationProperty("description", DefaultValue = "")]
public virtual string Description
{
get
{
return (string)this["description"];
}
}
}

以ConnectionStringElement为例,该实体定义三个属性信息:数据库连接字符串信息、数据库访问提供者、连接加密信息名称,其中连接加密名称填写时,使用ConnectionDecryptCollection中的定义解密类的类型信息进行反射实例化进行解密,不填写时则直接使用连接字符串信息。

 /// <summary>
/// 连接字符串配置项
/// </summary>
public class ConnectionStringElement:NamedConfigurationElement
{
/// <summary>
/// 连接字符串
/// </summary>
private string _connectionString = ""; /// <summary>
/// 连接字符串
/// </summary>
[ConfigurationProperty("connectionString")]
public string ConnectionString
{
get
{
if (!string.IsNullOrWhiteSpace(_connectionString))
return _connectionString;
var decryptName = ConnectionDecryptName;
if (string.IsNullOrWhiteSpace(decryptName))
_connectionString = (string)base["connectionString"];
else
{
DBConnectionConfiguration config = DBConnectionConfiguration.GetConfig();
var decrytType = config.ConnectionDecrypts[decryptName].Type;
IConnectionDecrypt cb = ReflectionHelper.CreateInstance(decrytType) as IConnectionDecrypt;
_connectionString = cb.Decrypt((string)base["connectionString"]);
}
return _connectionString;
}
} /// <summary>
/// DataProvider名称
/// </summary>
[ConfigurationProperty("providerName")]
public string ProviderName
{
get
{
return (string)base["providerName"];
}
} /// <summary>
/// 连接字符串加密方法名称
/// </summary>
[ConfigurationProperty("connectionDecryptName", DefaultValue = "", IsRequired = false)]
public string ConnectionDecryptName
{
get
{
return (string)base["connectionDecryptName"];
}
}
}
     /// <summary>
/// DataProvider配置项
/// </summary>
public class DataProviderElement: NamedConfigurationElement
{
/// <summary>
/// DataProvider类型信息
/// </summary>
[ConfigurationProperty("type")]
public string Type
{
get
{
return (string)base["type"];
}
}
}
     /// <summary>
/// 字符串加密方式配置项
/// </summary>
public class ConnectionDecryptElement:NamedConfigurationElement
{
/// <summary>
/// 字符串加密方式类型信息
/// </summary>
[ConfigurationProperty("type")]
public string Type
{
get
{
return (string)base["type"];
}
}
}

3. ConnectionStrings类

ConnectionStrings、DataProviders、ConnectionDecrypts三个配置列表实体,都会使用到使用配置项的名称获取对应的配置信息,因此需要将公共方法提取出来基类。

 public abstract class NamedConfigurationElementCollection<T> : ConfigurationElementCollection

     where T : NamedConfigurationElement, new()

 {

     /// <summary>
/// 按照名称获取指定的配置元素
/// </summary>
/// <param name="name">名称</param>
/// <returns>配置元素</returns>
public new T this[string name] { get { return (T)BaseGet(name); } } /// <summary>
/// 是否包含指定的配置元素
/// </summary>
/// <param name="name">配置元素名称</param>
/// <returns>是否包含</returns>
public bool ContainsKey(string name) { return BaseGet(name) != null; } /// <summary>
/// 添加元素
/// </summary>
/// <param name="obj"></param>
public virtual void Add(T obj)
{
BaseAdd(obj);
} /// <summary>
/// 得到元素的Key值
/// </summary>
/// <param name="element">配置元素</param>
/// <returns>配置元素所对应的配置元素</returns>
protected override object GetElementKey(ConfigurationElement element) { return ((T)element).Name; } /// <summary>
/// 生成新的配置元素实例
/// </summary>
/// <returns>配置元素实例</returns>
protected override ConfigurationElement CreateNewElement() { return new T(); }
}

定义基类后,ConnectionStrings、DataProviders、ConnectionDecrypts三个配置列表实体只需要继承该基类,不需要任何实现。

 public class ConnectionStringCollection: NamedConfigurationElementCollection<ConnectionStringElement>
{ } public class DataProviderCollection: NamedConfigurationElementCollection<DataProviderElement>
{ } public class ConnectionDecryptCollection: NamedConfigurationElementCollection<ConnectionDecryptElement>
{ }

通过以上配置实体类的定义,就可以使用以下方式获取到数据库配置信息:

DBConnectionConfiguration settings = DBConnectionConfiguration.GetConfig();

然后,根据数据库连接的名称获取到对应的信息,比如:

var connectionString = settings.ConnectionStrings[dbName].ConnectionString;

这里的DBName就是connectString配置项中的name信息。

ASP.NET MVC 学习笔记-7.自定义配置信息(后续)的更多相关文章

  1. ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则

    ASP.NET MVC 学习笔记-7.自定义配置信息   ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...

  2. ASP.NET MVC 学习笔记-7.自定义配置信息

    ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, <appSettings> <add key="LogInf ...

  3. ASP.NET MVC学习笔记-----使用自定义的View Engine

    我们都知道在ASP.NET MVC中自带了Razor View Engine,Razor十分的强大,可以满足我们绝大部分的需要.但是ASP.NET MVC的高度可扩展性,使我们可以使用自定义的View ...

  4. ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现

    ASP.NET MVC 学习笔记-2.Razor语法   1.         表达式 表达式必须跟在“@”符号之后, 2.         代码块 代码块必须位于“@{}”中,并且每行代码必须以“: ...

  5. ASP.NET MVC学习笔记-----Filter2

    ASP.NET MVC学习笔记-----Filter(2) 接上篇ASP.NET MVC学习笔记-----Filter(1) Action Filter Action Filter可以基于任何目的使用 ...

  6. ASP.NET MVC学习笔记-----Filter

    ASP.NET MVC学习笔记-----Filter(1) Filter类型 接口 MVC的默认实现 Description Authorization IAuthorizationFilter Au ...

  7. ASP.NET MVC学习笔记-----Filter(2)

    接上篇ASP.NET MVC学习笔记-----Filter(1) Action Filter Action Filter可以基于任何目的使用,它需要实现IActionFilter接口: public ...

  8. ASP.NET MVC学习笔记-----ControllerFactory

    上面这张图是asp.net mvc的工作流程图,我们可以看到当一个http请求来临时,首先需要经过路由系统,路由系统从中获取一些路由信息,然后ControllerFactory根据所得到的路由信息生成 ...

  9. ASP.NET MVC学习笔记-----ActionInvoker

    还是这张图: 当ControllerFactory生成Controller实例后,这时就需要使用ActionInvoker来选择调用一个合适的Action执行.ASP.NET MVC提供的基类Cont ...

随机推荐

  1. 算法第四版jar包下载地址

    算法第四版jar包下载地址:https://algs4.cs.princeton.edu/code/

  2. HDFS基本架构及概念介绍

    简单介绍 l  设计思想 分而治之:将大文件.大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析: l  在大数据系统中作用: 为各类分布式运算框架(如:mapred ...

  3. Visual Studio 常见的快捷键

    “Ctrl + -”               回到上一个光标位置 “Ctrl + Shift + -”                前进到下一个光标位置 “Ctrl + C”           ...

  4. JavaScript(变量、作用域和内存问题)

    JavaScript是一个变量松散型的语言.(不像Java一样强类型语言.) JavaScript变量包括两种:基本类型(简单的数据段)和引用类型(对象). 一.基本数据类型(5种) Undefine ...

  5. 背水一战 Windows 10 (98) - 关联启动: 使用外部程序打开一个文件, 使用外部程序打开一个 Uri

    [源码下载] 背水一战 Windows 10 (98) - 关联启动: 使用外部程序打开一个文件, 使用外部程序打开一个 Uri 作者:webabcd 介绍背水一战 Windows 10 之 关联启动 ...

  6. 为什么需要提前撰写Spec文档

    Joel on Software(中文名叫<Joel软件随想录>)算得上是一本旧书了,但里面的建议和讨论,真的是历久弥新.特别是,Joel是个有趣.牛逼的家伙:前微软Excel的职员.St ...

  7. 解决微信小程序的wx-charts插件tab切换时的显示会出现位置移动问题-tab切换时,图表显示错乱-实现滑动tab

    解决Echarts在微信小程序tab切换时的显示会出现位置移动问题 tab切换时,图表显示错乱 <canvas class="kcanvas" canvas-id=" ...

  8. 第46节:Java当中的常量池

    Java当中的常量池 在Java虚拟机jvm中,内存分布为:虚拟机堆,程序计数器,本地方法栈,虚拟机栈,方法区. 程序计数器是jvm执行程序的流水线,是用来存放一些指令的,本地方法栈是jvm操作系统方 ...

  9. (转)db2top详解

    原文:https://blog.csdn.net/lyjiau/article/details/47804001 https://www.ibm.com/support/knowledgecenter ...

  10. 如何测量并报告ASP.NET Core Web API请求的响应时间

    介绍 大家都知道性能是API的流行语.而相应时间则是API性能的一个重要并且可测量的参数.在本文中,我们将了解如何使用代码来测量API的响应时间,然后将响应时间数据返回到客户端. 作者:依乐祝 原文地 ...