在ArchOne平台中,为保证数据仓储层的纯粹性,仅实现数据仓储层本身最原始的数据库访问及操作功能,我们在设计之初即是在数据仓储类的构造函数中设置一个名为connectionString的参数传入数据库连接字符串的方式而不是通过传入数据库连接字符串名称(再由数据仓储层自身根据名称去查找配置文件中相应的数据库连接字符串)的方式实现数据仓储层。
同时,ArchOne平台中的各个对象的装配是通过Unity来实现的,默认情况下,我们在注册数据仓储接口类型时使用如下的配置代码:
< lifetime type ="singleton" />
< constructor >
< param name ="connectionString" value ="Data Source=.;Initial Catalog=数据库名称;User ID=用户名;Password=密码" />
</ constructor >
</ register >
但是,通过上述配置代码则将带来另外一个问题,如果我们的系统规模足够大,数据仓储类的注册将可能达到几十上百个,难道每一个注册配置中均直接写死数据库连接字符串吗?如果这样,假如我们需要更改数据库登陆密码,这将是一个非常庞大的工作,而且也容易出错,同时也违背了Microsoft在应用配置文件(web.config或app.config)中设置 connectionStrings 节点的初衷。
其实,Unity的开发团队为类似于这样的场景设计了更加友好的处理方式,当然,这需要我们对Unity进行一个简单的扩展,param节点可包含value子节点,在value节点中可定义值的类型转换器,我们更改后的配置文件如下:
< lifetime type ="singleton" />
< constructor >
< param name ="connectionString" >
< value value ="Center" typeConverter ="ConnectionStringConverter" />
</ param >
</ constructor >
</ register >
通过对比前后两处的配置文件,我们发现,第一个配置文件中直接定义了参数节点的值为数据库连接字符串,而在第二个配置文件中参数节点中仅定义了参数名称,但在其中包含了一个value节点,该value节点是对参数值进行进一步的配置,在该节点中,我们定义了value="Center",typeConverter="ConnectionStringConverter",其中的“Center”即表示应用配置文件(web.config或app.config)中connectionStrings节点下对应的数据库连接字符串配置节点的名称,而typeConverter中的“ConnectionStringConverter”则是我们对Unity进行扩展的一个“数据库连接字符串转换器”,该转换器的作用即是在Unity进行对象装配时自动将“数据库连接字符串名称”转换为对应的“数据库连接字符串”。
下面,我们简单介绍一下“ConnectionStringConverter”的实现:
1、添加一个类,名为ConnectionStringConverter,派生自 System.ComponentModel.TypeConverter;
2、重写基类中的 ConvertFrom 方法。
实现方式非常简单,直接贴出 ConvertFrom 方法中的代码如下:
if (value == null ) {
throw new ArgumentNullException( " value " );
}
if (value.GetType() != typeof ( string )) {
throw new ArgumentException( " value 必须为字符串类型。 " );
}
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[value.ToString()];
if (settings == null ) {
throw new Exception( string .Format( " 配置文件中不存在名为【{0}】的数据库连接字符串配置,请检查配置文件。 " , connectionStringName));
}
return settings.ConnectionString;
}