I attended a Skills Matter event recently on Castle Windsor. The presenters of the session were Mike Hadlow and Gojko Adzic. Slides, code samples and screencasts of the event can be found on their blogs. Mike's session was a very good introduction to dependency injection with IoC and Gojko tackled some of the more advanced features of Windsor such as facilities.
I've been using Castle Windsor for a while now on my current project favouring the use of a configuration file rather than registering components using code.
However, those of you who prefer registering your components in code will be pleased to find out that Castle have added a fluent interface to their API for Windsor. I've included an example below:
var container = new WindsorContainer();
container.Register(Component.For<ICatalogService>().ImplementedBy<MyCatalogService>().Lifestyle.Singleton);
The fluent interface is only available in the trunk version, so you'll need to download the source and compile it yourself.
I've been injecting all of my dependencies using the constructor but Mike also pointed out that Windsor also supports injecting dependencies using a property setter. This is useful if the dependency is optional. The configuration required to achieve this is the same as for constructor injection. In the following example catalogRepository is a constructor parameter and Logger is a property on the MyCatalogService class.
<container id="MyCatalogService"
service="MyNamespace.ICatalogService, MyAssembly"
type="MyNamespace.MyCatalogService, MyAssembly">
<parameters>
<catalogRepository>${MyCatalogRepository}</catalogRepository>
<Logger>${MyLogger}</Logger>
</parameters>
</container>
Something else mentioned was Windsor's support for generics. This is something I've had to tackle recently on my own project and is especially useful for mapping classes. The following is an example of how register a class (MyProductTypeMapper) which inherits from interface IMapper<Input, Output>.
public interface IMapper<Input, Output>
{
Output Map(Input input);
}
public class MyProductTypeMapper : IMapper<DBProductType, EntityProductType>
{
public EntityProductType Map(DBProductType input)
{
...
}
}
<container id="MyProductTypeMapper"
service="MyNamespace.IMapper`2[[MyNamespace.DBProductType, MyAssembly],[MyNamespace.EntityProductType, MyAssembly]], MyAssembly"
type="MyNamespace.MyProductTypeMapper, MyAssembly">
</container>
Mike also mentioned the new Common Service Locator library which is available on Codeplex. It is an abstraction around your IoC container of choice (Castle Windsor, Spring, Unity, StructureMap etc).
Also covered at the event was the use of Castle Windsor facilities. Castle provide a set of facilities out of the box including Logging, FactorySupport and NHibernate. There is also a MethodValidator facility available which allows you to add Design by Contract style functionality into your applications. An example was given using the StartableFacility which can be used to add standard functionality before and after each method call. This could be used for instance to log the entry and exit of each method. It is also possible to create custom facilities.
This is just a subset of the areas covered in the session. If you're interested in Castle Windsor then I'd urge you to watch the screencast of the session on Gojko's blog.