2013-02-21 80 views
5

我正在研究简化应用程序配置的库。本质上,库的使用者可以用属性装饰他们的配置类,或者用代码声明性地初始化这些设置。可以指定一个或多个来源来读取/写入配置属性(访问器)或从类继承默认值。例如,以下内容:包含属性中类型的库中DI的最佳实践

[ConfigurationNamespace(DefaultAccessors = new Type[] { typeof(AppSettingsAccessor) })] 
public class ClientConfiguration : Configuration<IClientConfiguration> 
{ 
    [ConfigurationItem(Accessors = new Type[] { 
     typeof((RegistryAccessor)) 
    })] 
    public bool BypassCertificateVerification { get; set; } 
} 

将相当于

var config = new Configuration<IClientConfiguration>(); 
config.SetDefaultAccessors(new[] { typeof(AppSettingsAccessor) }); 
config.SetPropertyAccessors(
    property: x => x.BypassCertificateVerification, 
    accessors: new[] { typeof(RegistryAccessor) } 
); 

的访问者应对阅读&从各种来源(的AppSettings,注册表的.ini,等等,等等)编写。我希望允许消费者扩展能力以满足他们的需求。我想保持它IoC容器不可知论者。 Type []约束是给我的,因为由于编译时和运行时问题,我无法在属性中指定类型。

有没有办法有用于实例默认这些机制(例如,基于Activator.CreateInstance东西),而且还允许消费代码来实例化这些访问在运行时不使用服务定位器/依赖解析器模式?我一直在阅读很多关于为什么服务定位器/依赖关系解析器模式是一个邪恶的反模式,但我找不出一个更好的工具。我使用依赖解析器查看MVC框架和SignalR库。他们是100%的时间还是这个边缘案例?据我所知,抽象工厂模式不会削减它,因为它不喜欢类型参数。

在这种特殊情况下,基于属性的配置将比声明式方法更有用,所以我不想放弃配置属性(这将允许我将Type更改为IConfigurationAccessor并切换到工厂方法)。

回答

5

从DSL上的工作中,我们知道将API与其他表达模式分离为基本的语义模型是很重要的。在这种情况下,Configuration<T> API在我看来就像是语义模型。没有理由在基于属性的DSL之后对语义模型进行建模。像这样会使更多的意义对我说:

var config = new Configuration<IClientConfiguration>(); 
config.DefaultAccessors.Add(new AppSettingsAccessor()); 
config.PropertyAccessorsFor(x => x.BypassCertificateVerification) 
    .Add(new RegistryAccessor()); 

我也想改变基于属性的模型是纯声明:

[AppSettingsConfiguration] 
public class ClientConfiguration : Configuration<IClientConfiguration> 
{ 
    [RegistryConfiguration] 
    public bool BypassCertificateVerification { get; set; } 
} 

现在你“只有”需要搞清楚一个从自适应模型转换为语义模型的方式。

基本上就像其他序列化阅读器:读取数据,并从类型注释中提示如何阅读它。这基本上是递归遍历数据结构,并且对于每个节点,您都需要创建一个Accessor。

假设所有访问者的实现像IAccessor的接口,这可以由可扩展与抽象工厂

public interface IAccessorFactory 
{ 
    IAccessor CreateAccessor(ConfigurationAttribute configurationAttribute); 
} 

其实,这是更具体叫产品交易不太广为人知的设计模式描述在PLoPD4,但由于大多数人不知道这种模式,我们只能称它为抽象工厂 - it's not a Service Locator,因为它不返回一个无界的类型 - 它只会返回IAccessor实例。

+0

我也在考虑DSL。我想到了一些沿着这些方向的东西,但是最终你会得到一个未加解析dsl的属性,这个属性几乎没有意义。 – 2013-02-22 16:25:58