As long as I have been using the Dependency Inversion Principle, Microsoft Unity has always been my preferred Inversion-of-Control framework. So it’s not strange that the Silverlight Cookbook has been using Unity 2 in both its WCF/REST layer as well as within the Silverlight client. I never even bothered looking at other frameworks, with the exception of NInject, that I used in a Windows Mobile 5 project, and StructureMap, of which I learned a lot while reading Jeremy D. Miller’s many posts of design patterns…
Let’s be honest though. I’ve always liked Unity and managed to use it to solve all my IoC and AOP problems without too much hassle. However, an analysis of some performance issues in my latest project revealed that its AOP features were not the fastest available. Notwithstanding, I would never simply change my strategy based on a single post. In fact, some claim that the comparison was faulty in the first place. But after browsing through the Autofac documentation I really became quite fond of Autofac’s strategy. I’ve always abided to the “Microsoft, unless…” philosophy, but my engineering heart couldn’t resist the temptation to try to introduce Autofac into the Silverlight Cookbook.
So what are the advantages?
Separation between configuration and resolution.
To be more precise, you use a ContainerBuilder to setup the dependencies like
And use its Build() method to construct an IContainer that you cannot change anymore. (Well, strictly speaking you can, but that doesn’t mean you should). Notice the fluent interface, one of the aspects of Autofac I like quite a lot.
This separation is actually the biggest reason why it took me so much time to migrate the Cookbook. You have to organize your setup code so that all registrations happen at the same place. But by doing so, I’ve found that my design actually became more clean with better separation of concerns. So, unlike what you might expect, I see this as an advantage rather than a disadvantage. But beware of this when you consider migrating from Unity to Autofac.
Implicit support for factory methods
Check out the updated version of the AddNewRecipeHandler:
So instead of introducing a dedicated factory interface, you can simply add a dependency to a Func<T> where T is your actual dependency. Autofac will automatically inject a delegate that you can use to create new instances of that dependency at will. And you don’t have to configure anything for that. It’s the caller that decides what kind of dependency he needs. And that’s not all. Autofac will keep track of any object you create that requires explicit disposal through its IDisposable interface. If you don’t want that, simply replace Func<T> with Owned<T>, which is Autofac’s way of giving you control. If you want to make this permanent for a particular registration, append ExternallyOwned() to the registration.
Collections of dependencies
Another feature I’ve always missed in Unity is support for taking a dependency on all instances of some type. And a big difference compared to Unity is that you can register as many implementations and instances of some interface as you want, without the need to specify some unique name.
Again, you don’t have to think about that during registration. It’s all part of Autofac’s extensive support for relationship types, which includes things like Lazy<T>, IIndex<T> or even Func<X, Y, B> if you need to parameterize the dependency somehow. And obviously you can combine those types to create some pretty advanced dependencies (although I wonder if you should).
If, you may wonder, you have to combine all type registrations in a single location, isn’t that code going to be very difficult to understand (and maintain)? Well, no. Autofac includes the notion of combining registration in so-called Modules. In the Cookbook I’ve used that mechanism to combine everything that is related to supporting the creating of units-of-work using NHibernate. So rather than code like this.
I can now do something like this:
Although the CookbookUnitOfWorkModule contains two more complex classes in its hierarchy that I introduced to simplify working with both SQL Server as well as SQLLite, the module concept makes it a breeze to work with.
What I particularly liked in the Managed Extensibility Framework is its support for scanning a directory for assemblies and automatically registering specific types. In the previous version of the Cookbook, I created hand-written code to automatically find my command handlers to overcome Unity’s lack of such functionality. Luckily, Autofac does include assembly scanning out-of-the-box, and now I can do this:
Yes, Autofac does not contain an equivalent of Unity’s [Dependency] attribute, and I think it’s great. In fact, Autofac’s preferred dependency injection mechanism is constructor injection. It will never inject (unset) properties, unless you explicitly configure it for that upon registration.
I’ve never liked property/setter injection because it allows an object to have many dependencies. According to my own coding guidelines and those stated by Clean Code, no member should ever have more than three parameters, not even the constructor. If you need that somehow, chances are your class has too much responsibility. So beware, because that is another of the pitfalls if you switch from Unity to Autofac.
Surely not everything is that great?
Well, in the beginning of my migration attempt I was a bit set back by the lack of property injection, the fact that you cannot create proxies of objects to intercept at any time in your code, and the explicit separation of configuration and resolution. However, after refactoring my code to accommodate for those changes, I noticed that I actually started to like those requirements. All in all, my code base has significantly improved because of those changes. But by now, it should be clear that a migration to Autofac may not be the best thing to do in most projects unless you’ve been clearly separating the responsibilities from the start. While looking back at all the code bases I’ve seen in my career, I think that ideal situation is not something you’ll encounter often….
This article is part of a series of posts dealing with all the choices and solutions used in the Silverlight Cookbook. If you have any comments, let me know by commenting or sending me a tweet on @ddoomen.