Question

I'm using the dictionary adapter as described in this blog post:

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

for getting app setting dependencies.

I have 2 attributes defined:

AppSettingsFromConfigAttribute - for holding a keyprefix

AppSettingsBehavior : KeyPrefixAttribute, IDictionaryPropertyGetter, IPropertyDescriptorInitializer

which is a carbon copy of the AppSettingsAttribute attribute class in the blog post.

This is the registration:

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);
                })));

So i use my custom attribute to avoid dependencies to Castle.Core throughout my codebase, but try and add the same behavior at runtime through the registration. This is working, the keyprefix part - but not the fetch part. This fails only on first use, not on construction.

If i use the AppSettingsBehavior statically on the interface, it works correctly, fetches and fails on construction. So where am i going wrong in adding behavior to the dictionary adapter?

Was it helpful?

Solution

After a few hours of looking at the source, scratching my head and a coffee. Found a solution :)

Basically in the addbehavior call i get to add dictionary behaviors, while what i need is an interface / property behavior to trigger (pre)fetch. In the source, the guys are checking for attributes on the supplied type all over the place, despite what the method signatures may say - but only taking dictionary initializers from the prop descriptor object, nothing for the interface / properties. Hence, even though the behavior i was adding had the interface behavior - it never got read, only the dictionary behaviors.

So, i use a different call. Instead of calling factory.GetAdapter - i instead get factory.GetAdapterMeta() - which gives me a meta object with a nice Properties getter - which has the collection for the actual interface properties.

So the code becomes:

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);
                })));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top