Combining MEF With Castle.Windsor For Low-Ceremony Component Composition
This is the first post in the endjin series on developing a loosely-coupled, ReSTful application architecture for .NET.
Here's a rough synopsis of the series.
- Component discovery and composition Part 1: Fundamentals
- Interlude 1 — Using conventions in your solution structure
- Component discovery and composition Part 2: Abstracting the container implementation
- Component discovery and composition Part 3: Configuration and lifetime management
The principles and patterns we're going to describe are pretty platform agnostic, but most of our examples will (obviously) make use of what we consider to be the best technology for the job, and get quite specific about the implementation details. Where possible, though, we will take the time to abstract away these platform-specific details so you can see how you might substitute in different vendor implementations to suit your own history and experience. And on the client side, we'll be using WPF, Silverlight and Web technologies to illustrate that these techniques apply to any kind of client experience. We'll also explain the reasoning behind our choices along the way (in fact, most of this first post is devoted to just that).
We're going to start the series with a post about the fundamentals of component discovery and composition, looking at the pros and cons of two technologies: MEF and Castle.Windsor.
The Managed Extensibility Framework (MEF) offers a great story for plug-in discovery and composition. It also has some of the features of a simple inversion-of-control (IOC) container. As an added bonus it is an in-the-box component of .NET 4.0 (with a separate download for earlier versions).
Castle.Windsor provides a first-class IOC container, with a discovery and composition story that lends itself to configuration by convention. It is a part of the Castle project, and made available under the Apache license (which makes it suitable for most Open- and Closed-source projects). You can download the Version 2.5.1 bits here.
What I'm going to walk through in this post is a way in which we can bring these two pieces together to provide a modular, low-ceremony way of bootstrapping components into a flexible, full-featured IOC container, that supports most (if not all) flavours of the .NET framework, including Silverlight. Although it covers the basics of both MEF and Castle.Windsor, it does so more to illustrate their differences than as a "getting started" guide. You'll find references in the notes at the end of each post which point to some good resources on both technologies.
So, what's the problem exactly?
Many (but by no means all) applications benefit from a loosely coupled, modular structure.
We want to make it easy for developers to design components independently from their colleagues, and that can be woven into our applications quickly and robustly in well-understood ways. We also want them to be testable, easily versioned (specifically, versioned independently) and easily deployed (we don't want to have to ship the whole system just to deliver one small new feature or fix a bug in one component).
These goals are largely achieved by giving our components well-defined boundaries and interfaces that are as self-describing as possible, that take a minimum of other dependencies, and that can be deployed in packages (assemblies, XAPs etc.) independently of one another.
What is a component?
When we say "component" we don't just mean a single entity (like a COM component of old, for example), but a small group of classes and perhaps other resources that are deployed together to provide a self-contained piece of functionality. So, to take an example on the client side, in an MVVM application, a view and its associated view model, along with any specific tasks and other supporting classes might be packaged together as a single component. They are all fairly tightly coupled with one another (although nicely layered within the component itself).
Typically, a component is packaged in a single assembly, although in certain circumstances it could be split across several. It is also a good idea for performance reasons (particularly at load time) to package lots of components up into a single assembly. We'll talk a little more about component packaging later in the series when we get to the piece on dealing with complexity.
A component, then, is quite a nebulous concept. You'll know it when you see it; but you should always try to design with components in mind as it is an important bounding constraint on the system, even if you are not going to go down the loosely-coupled, configuration driven road.
Back to the problem
So, in fact, we've got a whole lot of problems, but we're going to focus on four:
- How do you discover the components once they are deployed?
This is the discovery problem
- Once you've discovered them, where do you put them, and how do you get at them?
This is the container problem
- How do you wire them together?
This is the composition problem
- How do you make it easy for ordinary developers to get their classes to participate in this scheme without needing to understand a whole lot of framework-induced ceremony?
This is the big problem for developers and framework designers. How do you do something useful without also getting in the way?
MEF and Castle.Windsor both offer solutions to problems 1-3, with different trade-offs in terms of problem 4.
In the next post, we'll take a look at how they can help us.
Matthew Adams - @ythos