I’ve been using StructureMap for the last couple of months. I love it, and my only regret is that I didn’t start using it sooner. I always felt like I wrote clean, testable code before, but I can see a noticeable improvement since jumping on the IoC container bandwagon. If you aren’t using an IoC container and are working on anything above a trivially simple app, you should look in to it.
Anyway, I’m knee deep in rewriting our crawler infrastructure, and I found myself working with some classes that need access to external configuration data. The config data is all fairly simple stuff, for example: “the path to plug-ins”, “the number of threads to use here”, “the amount of time to wait before timing out”. We can argue about whether these things should actually be configurable outside of the code later, let’s just assume that they have to be for now. Well, in certain configurations, our crawler pulls these settings from the app.config file. In others, the settings are pulled from a configuration database. That immediately means that the code can’t just reference ConfigurationManager.AppSettings, it needs to access an abstraction, we’ll call it a configuration provider. Through the magic of IoC, all these configurable classes need to do is declare a dependency on this configuration provider, and the container will make sure they’re given whatever concrete config provider we have configured. This is an improvement over our previous approach, where we were declaring our config provider at the top-level of the application, then passing it down, down, down the call stack to the implementations that actually needed it. StructureMap has made things simpler, but it’s actually possible to improve things even further.
The very first version of our configuration provider abstraction looked something like this:
public interface IConfigurationProvider { string this[string settingName] { get; } }
Users of the provider (and by users here, I mean calling classes, not people) ended up sharing a lot of duplicate logic: extract a setting, make sure it’s there, try to convert it to the correct type, and substitute a default if all else fails. We improved things a bit with the second version of the abstraction:
public interface IConfigurationProvider { bool GetIntSetting(string name, out int holder, int defaultSetting); bool GetStringSetting(string name, out string holder, string defaultSetting); bool GetBooleanSetting(string name, out bool holder, bool defaultSetting); bool GetDoubleSetting(string name, out double holder, double defaultSetting); bool GetFloatSetting(string name, out float holder, float defaultSetting); }
This is better, now callers can get their settings in a single line of code, but there was still a lot of repetitive logic across the various users. There’s also a lot of magic strings in there. These can be encapsulated in consts, but they’re still there. Testing things that depend on these providers is also a little more difficult than it should be, though we do have a few classes to help.
A better solution would not depend on strings, would remove the burden of extracting settings from the caller, and be easy to mock or replace for testing. Perhaps something like this:
public class WidgetFactory { ... public WidgetFactory(WidgetFactorySettings settings) { this.Settings = settings; } ... }
Here, my class is saying “I depend on this configuration data”, and it would be swell if the IoC container could populate it magically with the correct settings. With just a small change, this actually becomes very easy to do:
public class WidgetFactory { ... public WidgetFactory(IConfiguration<WidgetFactorySettings> config) { this.Settings = config.Settings; } ... }
The interface for the provider is quite simple:
public interface IConfiguration<TSettings> where TSettings : new() { TSettings Settings { get; } }
At run-time, the IoC container will try to find a type to satisfy this dependency. No, you don’t have to create concrete types for everything that will ever need configuration data. All you need is one generic type per configuration source. Here’s a generic provider for extracting data from an app.config file:
public class AppConfigConfiguration<TSettings> : IConfiguration<TSettings> where TSettings : new() { public TSettings Settings { get; private set; } public AppConfigConfiguration() : this(ConfigurationManager.AppSettings) { } //You can easily unit test this class by giving it a NameValueCollection. internal AppConfigConfiguration(NameValueCollection appSettings) { Settings = new TSettings(); //Get properties we can potentially write from var properties = from prop in typeof (TSettings).GetProperties() where prop.CanWrite where prop.CanRead let setting = appSettings[typeof (TSettings).Name + "." + prop.Name] where setting != null where TypeDescriptor.GetConverter(prop.PropertyType).CanConvertFrom(typeof (string)) let value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromString(setting) select new {prop, value}; //Assign the properties. properties.ForEach(p => p.prop.SetValue(Settings, p.value, null)); } }
This provider uses a little bit of reflection and a little bit of LINQ to do it’s heavy lifting. It grabs all the public properties off of the generic TSettings type, then scans for values matching the format “{TypeName}.{PropertyName}”. If a match is found, and the value can be converted to the property’s concrete type, it is assigned.
We still need to give StructureMap a little bit of direction about how to resolve the IConfiguration<TSettings> type:
ObjectFactory.Container.Configure( config => { //We want to pull our configuration data from the app.config file. config.For(typeof (IConfiguration<>)).Use(typeof (AppConfigConfiguration<>)); } );
Now, anything that depends on an IConfiguration<whatever> will receive an AppConfigConfiguration<whatever>. If we want classes to pull their configuration data from a database instead, we simply adjust our StructureMap bootstrapping. Nothing else in the entire system has to change.
So, there you have it: a strongly-typed, generic, IoC-friendly way to handle your configuration data. Thoughts?
I wanted to thank you for this great read!! I definitely loved every little bit of it. I have you bookmarked your site to check out the latest stuff you post.
Cool post thanks. Very remarkable subject, will bookmark your blog to check if you write more about in the future.
Thanks for the fantastic post, I’m sure I’m not the only one of your readers that enjoy the well written material. Have a great day. I’m a professor of AP Courses, from Pennsylvania, and I am more inclined to think students of ap courses can use some help in writing like this. The only thing AP courses lacks is a more advanced writing section.<a href="http://www.course-notes.org">Ap courses</a>
Thanks for the fantastic post, I’m sure I’m not the only one of your readers that enjoy the well written material. Have a great day. I’m a professor of AP Courses, from Pennsylvania, and I am more inclined to think students of ap courses can use some help in writing like this. The only thing AP courses lacks is a more advanced writing section.<a href="http://www.course-notes.org">Ap courses</a>
Finally, Finally…I’ve been looking for this information for a long time. Thanks
I really appreciate the post, thanks again author. My wife and I are constantly searching for intelligient reads, and well, we found one here 🙂 If you’ve ever taken an AP Test, I think you’d agree that most writers who are in ap test classes lack proper structure. Even though taking an ap test isn’t a direct show of aptitude it does help develop succesful academic practices. More than one <a href="http://www.course-notes.org">Ap test</a> is currently available.
This is in a place that doesn’t even know what state it’s in: Wyoming, Minnesota?
As a web disigner I can say that your page was pretty interesting.Thanks for the insights.
ANNOUNCEMENT:</P><P>StimulusHomeBuyer.info is collecting all records on The Stimulus Bill for a Major Database update.This data is slated to be one of the largest informational datasets on the Stimulus Bill when it is completed. All information collected will be credited to the original Author.</P><P>For more information, please visit <A href="http://www.StimulusHomeBuyer.info">www.StimulusHomeBuyer.info</A></P>
its really very nice and informative posting thanks for sharing this with us…
Thanks mate and you are therefore welcome to visit me, of course you know what I mean. It will be interesting to learn what you make of my site.I will know whenever you do visit.
The text is really original and I have never seen a post like that before.
Clean blog. Wondering if you ever trade featured posts? I am maintaining a site on my current hobby akita dogs and looking to trade some articles with good pages. I checked out your blog and you’ve put up some great articles and I think our visitors would both benefit. Thanks!
I have been trying to Gain access to this website for a while. I was using IE7 then when I tried Safari, it worked just fine? Just wanted to bring this to your attention. This is really good website. I have a bunch myself. I really like your layout. I know this is off topic but,did you make this design yourself,or buy from somewhere?
Could you pls provide more points on this field??? Also your internet site is superior. Greets…
Great post thanks. Especially remarkable subject matter, will bookmark your site to check if you write further about in the future.
A lot of individuals of late have been asking me what steps they should take to resolve their spam troubles. Three client-side programmes come to mind – Cloudmark and Spamcop. These do a superb job of halting mail because people become part of a community. Your larger ISPs now provide a similiar service if they have a "report spam" button. Ultimately, people are, on average, a good read about what is spam, and what is not. Numerous major ISPs, such as hotmail.com, earthlink.net, and yahoo.com have got these features built-in.
<a href="http://quitsmokingr.com">Quit Smoking</a>
Intriguing posts. I bookmarked your site. I’m looking for other pages that have an audience that would get a benefit from a new site I maintain on akita dogs. Let me know if you want to exchange some posts or content. I think we could both get value.
I was just browsing for relevant blog posts for my project research and I happened to discover yours. Thanks for the excellent information! 🙂
Inspired thinking, I have bookmarked this and will come back to check
hello, this is my first time i visit here. I found so many interesting in your blog especially on how to determine the topic. keep up the awfullwork.
I haven’t any word to appreciate this post. nice post.
My wife and I have been using Acai powder supplement over the winter period. It’s given us a boost of energy during the dull weather. We’ve also managed to avoid the cold and flu germs everyone else seems to have. Will definitely continue using Acai.
Love the blog. Thanks so much for the information. I’ll be back to check out some more for sure.
Great post, very informative, thank you for sharing!
Informative website. On the topic of tech, you can learn more about computer keyboard
Thank you for such a great blog. Where else could anyone get this kind of info written in such an incite full way? I have a project that I am just now working on, and I have been on the look out for such info.
There are certainly many more details to take into consideration, but thanks for sharing this post.
You can implement blog tools such as Joomala, WordPress, Plone, CMS made simple, Mambo and many more have given the process of bulk submission to various web directories a new concept altogether.
I came across this surfing Google
Bonjour I would like to know where you got this site template from I love it!
If having trouble with your child’s Child Health Plus application and/or card where can you get assistance? You must recertify for Child Health Plus, Family Health Plus and Medicaid annually. A renewal application will be sent you in the mail and you are asked to return it promptly to renew your health insurance for another year. If you need assistance with your recertification you can contact the health plan in which you are enrolled, a community-based enroller or the Human Resources Administration at 311. http://www.freehealthinformation.net
I wanted to thank you for this excellent read!! I definitely loved every little bit of it. I have you bookmarked your site to check out the latest stuff you post.
Hey, I really like the look of your site. What template are you using?