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

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

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

针对配置信息中包括配置列表和配置项的要求,主要使用.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. noip第31课资料

  2. Python学习过程中各个难点---数据类型篇

    ---恢复内容开始--- 当时在学习python的基本数据类型时,对于可变与不可变类型不是了解的很透彻,这篇是回过头来自己的一些理解. 可变的数据类型有列表,不可变的数据类型有字符串,数字和元组   ...

  3. python3+redis问题求解

    学生管理系统   更新学生信息没做出来,找个大神补全下.谢谢. # 记录: # bug:操作后若退出需要两次退出才行. 待修复 # 下一步:链接redis进行使用. # 更新学生库信息 待完成 imp ...

  4. Android-MySQLiteOpenHelper的理解

    MySQLiteOpenHelper: package com.esandinfo; import android.content.Context; import android.database.s ...

  5. C#分部类型解析

    等待着元宵节的到来,过完元宵,这个年也算是过完了,也得开始出去挣钱了,过年回家感觉每个人都觉得很牛,只有自己太渣,为了避免年底再出现这样尴尬的局面,还是需要努力干活.争取当上CEO,赢取白富美,走上人 ...

  6. MySQL--MHA与GTID

    ##==========================================## MySQL 5.6版本引入GTID来解决主从切换时BINLOG位置点难定位的问题,MHA从0.56版本开始 ...

  7. 代码覆盖率 EclEmma

    1. EclEmma的介绍 EclEmma是一个开源的软件测试工具,可以在编码过程中查看代码调用情况.也可以检测单覆盖率. 2. Eclipse下EclEmma安装 1. 选择Help->Ecl ...

  8. Python学习笔记【第十四篇】:Python网络编程二黏包问题、socketserver、验证合法性

    TCP/IP网络通讯粘包问题 案例:模拟执行shell命令,服务器返回相应的类容.发送指令的客户端容错率暂无考虑,按照正确的指令发送即可. 服务端代码 # -*- coding: utf- -*- # ...

  9. 使用 VS Code 开发和调试 .NET Core 程序

    电脑不想装几十个G的 VS2017,那就用 VS Code 吧 目标: 创建一个类库项目 Skany.Core,并用 Nuget 引用第三方组件 Hash 实现加密算法 创建一个单元测试项目 Skan ...

  10. git gc和fsck的用法

    一.保证git良好的性能 在大的仓库中, git靠压缩历史信息来节约磁盘和内存空间. 压缩操作并不是自动进行的, 你需要手动执行 git gc: $ git gc 压缩操作比较耗时, 你运行git g ...