我正在开发一个简化应用程序配置的库。本质上,库的使用者要么用属性装饰他们的配置类,要么在代码中以声明方式初始化设置。可以指定 1 个或多个源来读取/写入配置属性(访问器)或从类继承默认值。例如,以下内容:
[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 并切换到工厂方法)。