Update: Please also read Part 2. The source is on github has been merged in Enterprise Library Contrib.
I tend to simplify exception handling at layer boundaries, when designing a distributed application. Most of the time if an exception is propagated there I try to apply some kind of policy in order to log the exception and then re-throw a different exception.
When I started using the Exception Handling Application Block from Enterprise Library I found out that I had to also deploy the Unity assemblies.
The call below resolves the registered component for the ExceptionManager class:
EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();
The IServiceLocator.Current property of EnterpriseLibraryContainer class sets by default the Unity container (via UnityServiceLocator adapter class).

In fact, if I remove the Unity assemblies a FileNotFoundException is thrown, indicating that Microsoft.Practices.Unity assembly or one of its dependencies could not be found.
Since I use Windsor in that application I didn’t like the fact that I had to deploy it with two different IoC containers (!) so I started figuring out how I can call tell the EnterpriseLibraryContainer to resolve the ExceptionManager component using Windsor.
The first thing I did was to compile the Windsor adapter of the CommonServiceLocator against the current version of Windsor that I use (and also run the unit-tests and see if they pass).
Next, I set the IServiceLocator.Current property of the EnterpriseLibraryContainer class:
EntLibraryContainer.Current = new WindsorServiceLocator(container);
The last thing I did was to call the ConfigureContainer method on the EnterpriseLibraryContainer class. This method takes an IContainerConfigurator and an IConfigurationSource as parameters.
Great, so I had to provide a class implementing the IContainerConfigurator interface for the Windsor container.
The IContainerConfigurator interface contains a single method:
void RegisterAll(
IConfigurationSource configurationSource,
ITypeRegistrationsProvider rootProvider
);
Below is the (currently incomplete) implementation:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel;
internal sealed class WindsorContainerConfigurator
: IContainerConfigurator
{
private readonly IWindsorContainer container;
public WindsorContainerConfigurator(IWindsorContainer container)
{
this.container = container;
}
public void RegisterAll(
IConfigurationSource configurationSource,
ITypeRegistrationsProvider rootProvider)
{
foreach (TypeRegistration registration
in rootProvider.GetRegistrations(configurationSource))
{
Register(registration);
}
}
private void Register(TypeRegistration registration)
{
Type implementation = registration.ImplementationType;
if (!this.container.Kernel.HasComponent(implementation))
{
var componentRegistration =
Component.For(registration.ServiceType)
.ImplementedBy(implementation);
if (registration.ConstructorParameters.Any())
{
var dependencies = GetRegistrationDependencies(
componentRegistration,
registration.ConstructorParameters);
componentRegistration =
componentRegistration.DependsOn(dependencies);
}
this.container.Register(AddLifeStyleToRegistration(
componentRegistration, registration.Lifetime));
}
}
private IDictionary GetRegistrationDependencies<TInterface>(
ComponentRegistration<TInterface> registration,
IEnumerable<ParameterValue> constructorParameters)
{
var dependencies = new Hashtable();
foreach (ParameterValue pv in constructorParameters)
{
MemberExpression exp = pv.Expression
as MemberExpression;
if (exp != null)
{
string key = exp.Member.Name;
object val = GetValue(exp);
dependencies.Add(key, val);
}
else
{
// TODO: pv.Expression is a MethodCallExpression.
}
}
return dependencies;
}
private static ComponentRegistration<TInterface> AddLifeStyleToRegistration<TInterface>(
ComponentRegistration<TInterface> registration,
TypeRegistrationLifetime typeRegistrationLifetime)
{
if (typeRegistrationLifetime ==
TypeRegistrationLifetime.Singleton)
{
registration = registration.LifeStyle.Singleton;
}
else if (typeRegistrationLifetime ==
TypeRegistrationLifetime.Transient)
{
registration = registration.LifeStyle.Transient;
}
else
{
throw new ArgumentOutOfRangeException(
"typeRegistrationLifetime",
"Only Transient and Singleton are supported.");
}
return registration;
}
private static object GetValue(Expression member)
{
var objectMember = Expression.Convert(member, typeof(object));
var getterLambda = Expression.Lambda<Func<object>>(objectMember);
return getterLambda.Compile().Invoke();
}
}
I really don’t know what to do in the case of a MethodCallExpression as you can see inside the else block. However, after I can finish with the code inside that block I will be able to do this:
var container = new WindsorContainer();
// Add a SubResolver for components with IEnumerable<T> dependencies on .ctors.
container.Kernel.Resolver.AddSubResolver(
new CollectionResolver(container.Kernel));
// This is the Windsor specific impl. of IContainerConfigurator interface.
var configurator = new WindsorContainerConfigurator(container);
// Configure the Enterprise Library Container to use Windsor internally.
EnterpriseLibraryContainer.ConfigureContainer(configurator,
ConfigurationSourceFactory.Create());
// Set Current property to a new instance of the WindsorServiceLocator adapter.
EnterpriseLibraryContainer.Current = new WindsorServiceLocator(container);
I will try to update the code as soon as I have done any changes.