sco*_*732 5 c# dependency-injection inversion-of-control
我正在开发一个简化应用程序配置的库.本质上,库的使用者要么使用属性装饰他们的配置类,要么在代码中以声明方式初始化设置.可以指定一个或多个源,从中读取/写入配置属性(Accessors)或从类继承默认值.例如,以下内容:
[ConfigurationNamespace(DefaultAccessors = new Type[] { typeof(AppSettingsAccessor) })]
public class ClientConfiguration : Configuration<IClientConfiguration>
{
[ConfigurationItem(Accessors = new Type[] {
typeof((RegistryAccessor))
})]
public bool BypassCertificateVerification { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
相当于
var config = new Configuration<IClientConfiguration>();
config.SetDefaultAccessors(new[] { typeof(AppSettingsAccessor) });
config.SetPropertyAccessors(
property: x => x.BypassCertificateVerification,
accessors: new[] { typeof(RegistryAccessor) }
);
Run Code Online (Sandbox Code Playgroud)
Accessors处理来自各种来源(AppSettings,注册表,.ini等等)的读写.我想让消费者扩展功能以满足他们的需求.我想保持IoC容器不可知.Type []约束是给我的,因为由于编译时与运行时问题,我无法在属性中指定类型.
有没有办法有一个默认机制来实例化这些(例如,基于Activator.CreateInstance的东西),但也允许消费代码在运行时实例化这些访问器而不使用服务定位器/依赖关系解析器模式?我一直在阅读很多关于为什么服务定位器/依赖解析器模式是一个邪恶的反模式,但我无法找到一个更好的工具.我看到MVC框架和SignalR库使用依赖解析器.他们100%的时间是邪恶还是这是一个边缘案件?据我所知,抽象工厂模式不会削减它,因为它不喜欢Type参数.
在这种特殊情况下,基于属性的配置比声明方法更有用,所以我不想放弃我的配置属性(这将允许我将Type更改为IConfigurationAccessor并切换到工厂方法).
从DSL工作开始,我们知道将API 与其他表达模式分离为底层语义模型非常重要.在这种情况下,Configuration<T>API看起来像是语义模型.在基于属性的DSL之后,没有理由对语义模型进行建模.这样的事情对我来说更有意义:
var config = new Configuration<IClientConfiguration>();
config.DefaultAccessors.Add(new AppSettingsAccessor());
config.PropertyAccessorsFor(x => x.BypassCertificateVerification)
.Add(new RegistryAccessor());
Run Code Online (Sandbox Code Playgroud)
我还将基于属性的模型更改为纯粹声明:
[AppSettingsConfiguration]
public class ClientConfiguration : Configuration<IClientConfiguration>
{
[RegistryConfiguration]
public bool BypassCertificateVerification { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在,您只需要找到一种从自适应模型转换为语义模型的方法.
这基本上与任何其他序列化读取器一样:读取数据,并从类型注释中获取有关如何读取它的提示.这基本上是递归遍历数据结构,并且对于每个节点,您需要创建一个Accessor.
假设所有Accessors都实现了类似的接口IAccessor,可以使用Abstract Factory进行扩展:
public interface IAccessorFactory
{
IAccessor CreateAccessor(ConfigurationAttribute configurationAttribute);
}
Run Code Online (Sandbox Code Playgroud)
实际上,这更具体地说是PLoPD4中描述的名为Product Trader的广为人知的设计模式,但由于大多数人不知道这种模式,我们只称之为抽象工厂 - 它不是服务定位器,因为它不是返回一个无界类型 - 它只返回IAccessor实例.
| 归档时间: |
|
| 查看次数: |
191 次 |
| 最近记录: |