使用Castle Dictionary Adapter的应用程序设置 - 在运行时添加行为

时间:2014-02-24 17:57:54

标签: c# castle-windsor castle

我正在使用此博客文章中描述的字典适配器:

http://kozmic.net/2013/11/21/on-strongly-typed-application-settings-with-castle-dictionaryadapter/

用于获取应用设置依赖项。

我定义了2个属性:

AppSettingsFromConfigAttribute - for holding a keyprefix

AppSettingsBehavior : KeyPrefixAttribute, IDictionaryPropertyGetter, IPropertyDescriptorInitializer

这是博客文章中AppSettingsAttribute属性类的副本。

这是注册:

Configure(component => component.UsingFactoryMethod(
                () =>
                {
                    var attrib = (AppSettingsFromConfigAttribute)Attribute.GetCustomAttribute(component.Implementation, typeof(AppSettingsFromConfigAttribute));

                    var prop = new PropertyDescriptor();

                    prop.AddBehavior(new AppSettingsBehavior(attrib.KeyPrefix));

                    return configFactory.GetAdapter(component.Implementation, new NameValueCollectionAdapter(ConfigurationManager.AppSettings), prop);
                })));

所以我使用自定义属性来避免在整个代码库中依赖于Castle.Core,但尝试通过注册在运行时添加相同的行为。这是有效的,keyprefix部分 - 但不是fetch部分。这只在第一次使用时失败,而不是在构造时失败。

如果我在界面上静态使用AppSettingsBehavior,它可以正常工作,获取并构建失败。那么我在向字典适配器添加行为时会出错?

1 个答案:

答案 0 :(得分:0)

看了几个小时后,抓了我的头,喝了一杯咖啡。找到了解决方案:)

基本上在addbehavior调用中我会添加字典行为,而我需要的是触发(预)获取的接口/属性行为。在源代码中,这些人正在检查所提供类型的属性,尽管方法签名可能会说 - 但只是从prop描述符对象中获取字典初始化器,对于接口/属性没有任何内容。因此,即使我添加的行为具有接口行为 - 它从未被读取,只有字典行为。

所以,我使用不同的电话。而不是调用factory.GetAdapter - 我改为factory.GetAdapterMeta() - 它给了我一个带有一个很好的属性getter的元对象 - 它有实际接口属性的集合。

所以代码变成:

Configure(component => component.UsingFactoryMethod(
                () =>
                {
                    var attrib = (AppSettingsFromConfigAttribute)Attribute.GetCustomAttribute(component.Implementation, typeof(AppSettingsFromConfigAttribute));

                    var prop = new PropertyDescriptor();

                    prop.AddBehavior(new AppSettingsBehavior(attrib.KeyPrefix));

                    var meta = configFactory.GetAdapterMeta(component.Implementation);

                    foreach (var entry in meta.Properties)
                    {
                        entry.Value.Fetch = true;
                    }

                    return meta.CreateInstance(new NameValueCollectionAdapter(ConfigurationManager.AppSettings), prop);
                })));