hypnocode delusions from a sleepless mind…

5Dec/11Off

Convention Based Settings with Unity

Over the summer, I read a post by Chad Myers discussing easy configuration in FubuCore. At the time I thought this was a really nice idea, but forgot about it as I was more into an upcoming vacation to Iceland. Then last week I was reminded of Chad's post when I came across Josh Bush's blog post taking the easy configuration idea and implementing it with Autofac. If you want further details on this easy configuration idea I'll let you go read either Chad's or Josh's post, but the overall view goes something like this.

Many applications take dependencies on external configuration settings, either from a config file, database or some other source. You end up littering your code with ConfigurationManager calls all over or wrapping everything behind a class to hide the details. Instead, what if you injected your classes with a simple POCO object and your container of choice would populate the properties of your object when it gets resolved.

Josh's implementation of this idea was for Autofac. If you haven't been able to tell from some of my prior posts, I use Unity at work, so I thought it would be nice to see if I could do something similar for it. I will admit, the core of my implementation comes from Josh's code base. I didn't see any need to reinvent the wheel on it and instead spend my time trying to figure out how to wire this up in Unity.

I'll be honest, I haven't done much more with Unity other then the necessary registering and resolving of objects, so I dug around a bit to figure out the best way to go about this. I finally decided that creating an extension of the Unity container was the easiest way to do it. Here is the extension that I came up with.

public class SettingsProviderExtension : UnityContainerExtension
{
   protected override void Initialize()
   {
      Container.RegisterType<ISettingsFactory, SettingsFactory>("DefaultSettingsFactory", new ContainerControlledLifetimeManager());
      Container.RegisterType<IEnumerable<ISettingsProvider>, ISettingsProvider[]>();

      Context.Strategies.Add(new BuildUpSettingsStrategy(), UnityBuildStage.Initialization);
   }
}

internal class BuildUpSettingsStrategy : BuilderStrategy
{
   public override void PreBuildUp(IBuilderContext context)
   {
      if (context.Existing != null
            && context.Existing.GetType().IsClass 
            && context.Existing.GetType().Name.EndsWith("Settings")) {
         var settingsFactory = GetSettingsFactory(context);
         settingsFactory.BuildUp(context.Existing);
      }
   }

   private static ISettingsFactory GetSettingsFactory(IBuilderContext context)
   {
      var factory = context.NewBuildUp("DefaultSettingsFactory");
      if (factory == null) {
         throw new InvalidOperationException("No instance of ISettingsFactory available.");
      }

      return factory;
   }
}

The extension starts by registering a SettingsFactory which is used to look through a collection of ISettingsProvider types (the implementation of these types comes straight from Josh's code base). I have no idea if this is okay to do inside of an extension or not, but it seems to work. You can always move it out and register it on your own if you wish, especially if you change the implementation of it up. Then I add a new BuildUpSettingsStrategy to Unity that will run at the initialization stage. This stage occurs after the object being resolved has been created. The new strategy looks at the class being resolved, checks to see if it is an actual class type and if the type name ends with "Settings", and if it matches all of these it will set the properties of the class using the SettingsFactory we registered in the container.

To use this, you just need to setup your POCO settings class and register this extension with the container.

public class WorkerSettings
{
   public string Server { get; set; }
   public int Port { get; set; }
}

public class Worker
{
   private readonly WorkerSettings _settings;

   public Worker(WorkerSettings settings)
   {
      _settings = settings;
   }

   public void DoWork()
   {
      Console.WriteLine("Connecting to {0}:{1}", _settings.Server, _settings.Port);
   }
}

class Program
{
   static void Main(string[] args)
   {
      IUnityContainer container = new UnityContainer();
      container
         .AddNewExtension<SettingsProviderExtension>()
         .RegisterType<ISettingsProvider, AppSettingsProvider>("AppSettingsProvider", new ContainerControlledLifetimeManager());

      container.Resolve<Worker>().DoWork();
   }
}

This will pull configuration information from the app.config file.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <appSettings>
      <add key="WorkerSettings.Server" value="example.com" />
      <add key="WorkerSettings.Port" value="81" />
   </appSettings>
</configuration>

I put this entire project up on github (mainly as an excuse to play with git, I know, I'm late to the game) along with a trivial demo application so if you want to take a look at the source, it's up there. Next, maybe I'll look at putting together a NuGet package as an excuse for creating my first NuGet package.

Filed under: dev, unity No Comments
7Sep/10Off

Unity Configuration Tricks

Okay, not so much tricks, but just a single trick. I'm not going to get into the whole debate on which dependency injection container is better. I've played around with several in the past. My employer has standardized on using Unity for deployable projects (they go with the Microsoft tool sets and I'm in no position to change that), so this is the container I know best.

One of the things we do is configure Unity at run-time, either directly or through auto registration depending on the size of the project. However, during development, I like to take advantage of the face that if you register two classes to the same interface, Unity uses a last one registered wins strategry. So something like:

container.RegisterType<IService, ServiceOneImpl>();
container.RegisterType<IService, ServiceTwoImpl>();

would always return to you the ServiceTwoImpl instance what you ask the container for IService. Now, doing this in code is not ideal. Instead I register everything in code like normal and then once setup, I take advantage of the registration through the config file:

container.RegisterType<IService, ProductionServiceImpl>();

UnityConfigurationSection section =
   (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
if ((section != null) && (section.Containers.Count > 0)) {
   section.Configure(container);
}

Now I can override production values at runtime by specifying them within the config file. This has helped by letting me and others work on new things within the production application without touching the main code for the application. It has also helped a time or two to figure out a few "works fine on every machine but this one" scenarios as we can toss in a specially instrumented version of a class and see more of what is going on.

Its no substitute for TDD, but has provided us with a helpful way of doing things more than once in the past.

If you are worried about releasing this in a production application, then you can always through an #ifdef around the config file loading and only do so on DEBUG builds of your code.

Filed under: dev, unity No Comments