Cool stuff in FubuCore No. 5: Easy Configuration

This is the fifth post of the FubuCore series mentioned in the Introduction post.

In the whole history of FubuMVC, we’ve developed and innovated a bunch of cool stuff. Some of it can be complicated but has a big payoff.  But there are also a bunch of small, little cool things that make a big difference. One of those things was the ISettingsProvider.  It was one of those ideas that we could’ve come up with a long time ago, before FubuMVC, but it had just never occurred to us.  I wish I had this way back when, because it would’ve been invaluable to me on many projects.  I can’t tell you how much stupid code I’ve written in my .NET career just to work around a lot of the System.Configuration nonsense. “Nonsense?” you say. Perhaps I should have said “mystery” as in, a mystery that needs to be unraveled, decoded, and cracked.  I’m sure someone once had problems that this framework solved, but for most of us, we just need something less complicated than this.

I kept finding myself saying, “Dang, I wish I could just get my settings injected like everything else” (settings are a dependency, after all).   And I don’t want some sort of “SettingsFactory” that needs injected that I then have to go query for my configuration because that gets nasty to test (lots of mocks and interaction testing). What I really want is just a POCO object that represents my settings and have someone else figure out how to get those settings from whatever configuration source and bind them to my POCO settings class. 

The Settings Provider

This is where ISettingsProvider comes in. It works behind the scenes with my IoC container to set up my settings class. Consider this simple POCO settings class:

public class SampleSettings
{
    public string Name { get; set; }
    public int Age { get; set; }
    public bool Active { get; set; }
}

Let’s say I want this thing injected (via constructor injection, for example) into my controller.  Then I can use my settings in my action(s) just like normal. My controller would never have to even know about System.Configuration or AppSettings or anything like that.

My controller might look like this:

public class SampleController
{
    private SampleSettings _settings;
    
    public SampleController(SampleSettings settings)
    {
        _settings = settings;
    }
    
    public SampleOutputModel Index(SampleInputModel model)
    {
        return new SampleOutputModel{ Aget = _settings.Age };
    }
}

As a side note: In FubuMVC, controllers don’t have to derive from any base classes and actions just take in and return models because controller actions shouldn’t have the extra responsibility of choosing what type of output goes back to the client. In FubuMVC, you describe how actions are wired up to views or JSON or whatever the appropriate response is to the requesting HTTP client. But I digress…

In this SampleController example, you can see that my settings are injected via the constructor and then used in a controller action just like you would expect.

How it all gets wired up

Scan for Settings classes

In your StructureMap Registry class, add a “Scan” block that uses the SettingsScanner from FubuMVC. If you just want to use FubuCore in your project and not FubuMVC, then just copy SettingsScanner into your project, it’s not that big.

The new “Scan” section in your Registry would look something like this:

x.Scan(s =>
{
    s.TheCallingAssembly();
    s.Convention<settingsscanner>();
});

SettingsScanner will scan all the assemblies you tell it about (“TheCallingAssembly” in this case) for any concrete classes whose names end with “Settings”.  It will then wire them up in StructureMap so that whenever a class has a dependency on a *Settings class, StructureMap will use the configured ISettingsProvider to “fill” your Settings POCO class from whatever configuration source(s) you’re using. For those familiar with StructureMap configuration parlance, that would be:

For(type)
   .LifecycleIs(InstanceScope.Singleton)
   .Use(c => c.GetInstance<ISettingsProvider>()
       .SettingsFor(type));

 

Register a settings provider

The next thing you have to do is tell StructureMap which ISettingsProvider you want to serve up your *Settings classes.

Currently, FubuCore ships with one built-in: the AppSettingsProvider.  As you might imagine, this will bind your settings classes and their properties to appSettings keys in your .config files.  It follows a specific convention for appSettings keys, which is:  [SettingsClassName].[PropertyName].   Consider the example class above (SampleSettings).  To wire up the Age property, the resulting appSettings entry would look like this:

<appSettings>
    <add key="SampleSettings.Age" value="29"/>
</appSettings>

 

That’s pretty much it. Wire up the scanner, wire up an ISettingsProvider implementation, make a Settings class, and add it as a constructor dependency and it should just all work.

Future

Hopefully you can see a bunch of possibilities with the ISettingsProvider. We’ve imagined doing all sorts of things which should be possible:

  • Loading settings from the Database
  • Loading settings from an encrypted storage source
  • Loading settings dynamically every time they’re requested (allowing for runtime setting changes without needing to restart the app)
  • Loading settings from multiple config sources (some in the DB, some in config files, some in encrypted storage)

(the more observant among you probably noticed our imagination of the future does not involve System.Configuration if we can help it).

In fact, the Bottles deployment stuff that Jeremy and Dru are doing that I mentioned in the last post involves a multi-config source settings provider that provides a lot of flexibility in configuration and deployment. Keep an eye out for that in the near future from either Jeremy or Dru.

Summary

Hopefully you got some useful ideas and practical next steps from this post. If you come up with any cool ISettingsProviders in your usage, please let us know and contribute them back if they’re not “secret sauce” for you.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Chad Myers

Chad Myers is the Director of Development for Dovetail Software, in Austin, TX, where he leads a premiere software team building complex enterprise software products. Chad is a .NET software developer specializing in enterprise software designs and architectures. He has over 12 years of software development experience and a proven track record of Agile, test-driven project leadership using both Microsoft and open source tools. He is a community leader who speaks at the Austin .NET User's Group, the ADNUG Code Camp, and participates in various development communities and open source projects.
This entry was posted in .NET, cool-stuff-in-fubu, fubucore, FubuMVC. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://twitter.com/jeremydmiller jeremydmiller

    The “multi-config” version of ISettingProvider is in FubuCore now.  Someday I’ll guilt Dru into blogging about it;-)

  • Joseph Vano

    I love this feature … in everything.

    Keep up the barrage of Fubu posts.

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #866

  • Harry Dev

    So the multi config would be able to handle multiple config files such as xml? And could you use path information to direct same types of configuration to specific “instances”? I.e. given CommonSettings and two consumers Foo(CommonSettings settings) and Bar(CommonSettings settings) could two files from “SettingsFooCommonSettings.xml” and “SettingsBarCommonSettings.xml”?

    • http://chadmyers.lostechies.com Chad Myers

      @2b3f8241a91521c722d9ab1252697ab5:disqus Actually, it’d be more like:   commonSettings.config and then userOverrides.config.  The user overrides would take precedence over commonSettings

  • Kevin Miller

    I use this all the time in projects. It is fantabulous. The one thing I’d like to improve about it is to memonize the settings once they are materialized.

    • http://chadmyers.lostechies.com Chad Myers

      Kevin, the SettingsScanner in FubuCore sets them to be InstanceScope(Singleton) so they’re not loaded every time. 

  • clayton collie

    I just started using this and its fantastic. However it took me the better part of the day to wire it up (mostly by looking at FubuMVC registration). So for fellow travellers, ensure that your IOC registration is similar to the following :

        public class SettingsRegistry : Registry
        {
            public SettingsRegistry()
            {
                Scan(x =>
                         {
                             x.AssemblyContainingType();
                             x.AssemblyContainingType();
                             x.Convention();
                         });

                For()
                    .Use(new FolderAppSettingsXmlSource(GetConfigPath()));
            

                For().Use();
                For().Use();
                For().Use();
                For().Use();
                ForSingletonOf().Use();
                ForSingletonOf().Use();
                ForSingletonOf().Use();
                For().Use();

                For()
                    .Use();

                //SetAllProperties(s => s.Matching(p => p.Name.EndsWith(“Settings”)));
            }

            internal static string GetConfigPath()
            {
                var dir = AppDomain.CurrentDomain.BaseDirectory;
                var path = System.IO.Path.Combine(dir, “configuration”);
                return path;
            }

  • clayton collie

    Sorry for the messed up comments. Just check out the registration from FubuMVC.

  • http://www.ocularconcepts.us Web Design Firm

    Loading settings from multiple config sources would be the coolest future item I believe. Thanks for this elaborate post

  • http://www.facebook.com/people/Deborah-Smith/100002400274841 Deborah Smith

     I haven’t tried this one but with your review I think I should try it. It can help my small project for an online venture. thanks. buy and sell