通过ConfigurationManager使用.NET配置文件时,可以通过添加配置文件进行单元测试,虽然可以通过测试但达不到解耦的目的。使用IConfigurationManager和ConfigurationManagerWrapper对ConfigurationManager进行适配是更好的方式,ConfigurationManagerWrapper提供.NET配置文件方式的实现,如果需要支持其他配置,创建IConfigurationManager接口的不同的实现类即可。
1.定义IConfigurationManager接口
原本依赖ConfigurationManager的代码现在依赖IConfigurationManager。可以在单元测试时方便的Mock。
public interface IConfigurationManager
{
NameValueCollection AppSettings { get; }
ConnectionStringSettingsCollection ConnectionStrings { get; }
object GetSection(string sectionName);
}
2.创建适配类ConfigurationManagerWrapper
非单元测试环境使用ConfigurationManagerWrapper作为IConfigurationManager的默认实现。
public class ConfigurationManagerWrapper : IConfigurationManager { public NameValueCollection AppSettings { get { return ConfigurationManager.AppSettings; } } public ConnectionStringSettingsCollection ConnectionStrings { get { return ConfigurationManager.ConnectionStrings; } } public object GetSection(string sectionName) { return ConfigurationManager.GetSection(sectionName); } } |
3.自定义泛型配置接口
在我们的代码需要使用配置时,可以考虑创建通用的泛型接口也可以使用专用的强类型的接口。这里演示使用通用的接口。
public interface IConfiguration
{
T Get<T>(string key, T @default);
}
4.实现泛型接口配置接口的.NET配置文件版本
AppConfigAdapter直接不使用ConfigurationManager而是依赖IConfigurationManager接口。 public class AppConfigAdapter : IConfiguration { private IConfigurationManager _configurationManager; public AppConfigAdapter(IConfigurationManager configurationManager) { this._configurationManager = configurationManager; } public T Get<T>(string nodeName, T @default) { var value = this._configurationManager.AppSettings[nodeName]; return value == null ? @default : (T)Convert.ChangeType(value, typeof(T)); } } |