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

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

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

针对配置信息中包括配置列表和配置项的要求,主要使用.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. 利用Qt Designer 进行 空间提升propomotion 的时候异常: NO such file or directory

    1. 因为在提升的时候,只设置了 类名,以及文件名,但是没有给定Qt 的uic 的指定搜索路径,因此报错 在生成的ui_xxxx.h文件必然找不到这个文件. 如下图: 2. 解决方法 在项目的属性中: ...

  2. idea 2017破解的三种方式

    1.该方法最为简便,但是该方法只可以在联网时使用,打开idea主页,找到最后面的Help,打开,找到register-license server, 在输入http://idea.iteblog.co ...

  3. Java基础知识提要

    1. 简述Java的基本历史 java起源于SUN公司的一个GREEN的项目,其原先目的是:为家用消费电子产品发送一个信息的分布式代码系统,通过发送信息控制电视机.冰箱等   2. 简单写出Java特 ...

  4. [转] List of OpenFlow Software Projects

    List of OpenFlow Software Projects (that I know of) http://yuba.stanford.edu/~casado/of-sw.html (I a ...

  5. 项目Alpha冲刺(团队6/10)

    项目Alpha冲刺(团队6/10) 团队名称: 云打印 作业要求: 项目Alpha冲刺(团队) 作业目标: 完成项目Alpha版本 团队队员 队员学号 队员姓名 个人博客地址 备注 221600412 ...

  6. Spring+Redis集成+关系型数据库持久化

    本篇文章主要介绍了"Spring+Redis集成+关系型数据库持久化",主要涉及到Spring+Redis集成+关系型数据库持久化方面的内容,对于Spring+Redis集成+关系 ...

  7. python之asyncio

    asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持. asnycio是用来编写并发代码的库,python3.5以后使用async/await语法. asyncio 被用作 ...

  8. Spring整合MyBatis 你get了吗?

    Spring整合MyBatis 1.整体架构dao,entity,service,servlet,xml 2..引入依赖 <dependencies> <dependency> ...

  9. ubuntu垃圾文件清理方法

    linux和windows系统不同,linux不会产生无用垃圾文件,但是在升级缓存中,linux不会自动删除这些文件,今天就来说说这些垃圾文件清理方法. 1,非常有用的清理命令:sudo apt-ge ...

  10. vue 项目实战 (生命周期钩子)

    开篇先来一张图 下图是官方展示的生命周期图 Vue实例的生命周期钩子函数(8个)        1. beforeCreate             刚 new了一个组件,无法访问到数据和真实的do ...