自定义配置信息的高级应用
通过上篇博文对简单的自定义配置信息的学习, 使得更加灵活的控制系统配置信息. 实际项目中, 这种配置的灵活度往往无法满足项目的灵活度和扩展性.
比如, 一个配置信息有三部分组成, 而每部分中有包括一些配置信息. 仅仅使用简单的自定义配置无法满足, 因此, 需要提供更多的自定义配置方法来灵活实现.
针对配置信息中包括配置列表和配置项的要求, 主要使用. 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 信息.
来源: http://www.bubuko.com/infodetail-2608298.html