This project is read-only.

Migrating from Simple Injector to Caste Windsor

Castle Windsor is part of the Castle Project. It is one of the oldest and most used DI frameworks for .NET. It offers a very rich and extensible API. Advanced scenario’s however, are often hard to implement unless you have a very good understanding of the complete API.

Website http://www.castleproject.org/castle/projects.html
Download http://www.castleproject.org/castle/download.html
Supported platforms .NET 3.5 (and up), Silverlight 3 (and up)
Code samples based on version 2.5.3.

Core differences with Simple Injector

  1. The default lifestyle is Singleton.
  2. Every resolved instance has to be releases explicitly to prevent memory leaks.
  3. Tends to swallow errors, which makes it hard to find configuration bugs.
  4. By default, concrete instances can not be resolved without registration.
  5. Scans new instances for writeable properties and assigns a value if it can provide a component that matches the type of the property (implicit property injection).
  6. Does not allow resolving collections of objects through constructor injection by default. Add the ArrayResolver to allow resolving arrays. Add the EnumerableResolver to allow resolving IEnumerable<T> collections.

Code Samples

The following section contains code snippets that show how to resolve and register instances with the Simple Injector on the left-hand side, and equivalent snippets for Castle Windsor on the right-hand side.

Resolving Instances

Simple Injector Castle Windsor
container.GetInstance<IService>(); container.Resolve<IService>();
container.GetInstane(typeof(IService)); container.Resolve(typeof(IService));
IEnumerable<IFilter> filters = container.GetAllInstances<IFilter>(); IFilter[] filters = container.ResolveAll<IFilter>();
IEnumerable<object> filters =
    container.GetAllInstances(typeof(IFilter));
IFilter[] filters =
    container.ResolveAll(typeof(IFilter));

Registration

Registration with a transient lifetime.
Simple Injector Castle Windsor
// Optional. Concrete instances can be
// resolved without registration
container.Register<RealService>();
// Required. Concrete instances will not 
// be resolved without registration.

container.Register(Component 
    .For<RealService>().LifeStyle.Transient);
container.Register<IService, RealService>(); container.Register(Component.For<IService>()
    .ImplementedBy<RealService()
    .LifeStyle.Transient);
container.Register<IService>(() =>

    var log = container.GetInstance<ILogger>(); 
    return new RealService(logger);
});
container.AddFacility<FactorySupportFacility>();

container.Register(Component.For<IService>()
    .UsingFactoryMethod(() =>
    {
        var log = container.Resolve<ILogger>();
        return new RealService(log);
    })
    .LifeStyle.Transient);
Registration with a singleton lifetime.
Simple Injector Castle Windsor
container.RegisterSingle<RealService>(); container.Register(Component.For<RealService>());
container
    .RegisterSingle<IService, RealService>();
container.Register(Component.For<IService>().ImplementedBy<RealService>());
container.RegisterSingle<IService>(() =>
{  
  var log = container.GetInstance<ILogger>();  
  return new RealService(log);
});
container.AddFacility<FactorySupportFacility>();

container.Register(Component.For<IService>()
    .UsingFactoryMethod(() =>
    {
      var log = container.Resolve<ILogger>();
      return new RealService(log);
    }));
container.RegisterSingle<IService>( 
  new RealService(new ConsoleLogger()));
container.Register(Component.For<IService>()
    .Instance(
        new RealService(new ConsoleLogger())));
container.RegisterAll<IFilter>( 
    new XssInjectionFilter(), 
    new SqlInjectionFilter(), 
    new SmartFilter()
);
container.Register(Component.For<IFilter>()
    .Instance(new XssInjectionFilter()));
container.Register(Component.For<IFilter>()
    .Instance(new SqlInjectionFilter()));
container.Register(Component.For<IFilter>()
    .Instance(new SmartFilter()));
IEnumerable<IFilter> filters = 
    FilterProvider.GetFilters();
container.RegisterAll<IFilter>(filters);
[not clear how to achieve this with Windsor]
container.RegisterInitializer<ICommand>(cmd =>
{  
    cmd.Logger =
        container.GetInstance<ILogger>();
});
// Castle Windsor will implicitly inject all
// writable properties for you. There’s nothing
// you need to do here.
container.RegisterInitializer<ICommand>(cmd =>

    cmd.SendAsync = true
});
// The closest thing with Windsor is this:
container.Register(AllTypes.From( 
    AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(a => a.GetExportedTypes()))
    .BasedOn<ICommand>()
    .WithService.Self()
    .Configure(c => c.DependsOn(Property
        .ForKey("SendAsync").Eq(true))
        .LifeStyle.Transient));

// Note that this is still not equivalent to the
// left side, since this Windsor registration
// is a batch registration, while the Simple
// Injector’s RegisterInitializer is just a hook
// for any type that implements ICommand. It does
// not register any type itself. Also note that
// the Windsor registration is not type-safe,
// since the name of the property is a string.
// This will break when the property name is
// refactored.

Advanced Scenarios

The SimpleInjector.Extensions.dll contains extension methods for the Container class that enable many advanced scenario’s. The section below how the registrations done with the Extensions library maps to those of Castle Windsor.

Registration using the non-generic API.
Simple Injector Castle Windsor
container.Register(typeof(IService),
    typeof(RealService));
container.Register(Component 
    .For(typeof(IService))
    .ImplementedBy(typeof(RealService))
    .LifeStyle.Transient);
container.RegisterAll<IFilter>(
    from asm in AppDomain.CurrentDomain
        .GetAssemblies()
    from type in asm.GetExportedTypes()
    where !type.IsAbstract
    where typeof(IFilter).IsAssignableFrom(type)
    select type);
container.Register(AllTypes.From( 
    AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(a => a.GetExportedTypes()))
    .BasedOn<IFilter>()
    .WithService
        .Select(new[] { typeof(IFilter) })
    .Configure(c => c.LifeStyle.Transient));
Batch registration of generic interfaces
Simple Injector Castle Windsor
container.RegisterManyForOpenGeneric(
    typeof(IHandler<>),
    typeof(IHandler<>).Assembly);
container.Register(AllTypes
    .FromAssemblyContaining(typeof(IHandler<>))
    .BasedOn(typeof (IHandler<>))
    .Unless(t => t.IsGenericTypeDefinition)
    .WithService.Select((_, baseTypes) =>
    { 
        return
            from t in baseTypes
            where t.IsGenericType 
            let td = t.GetGenericTypeDefinition()
            where td == typeof(IHandler<>)
            select t;
    })
    .Configure(c => c.LifeStyle.Transient));
container.RegisterManyForOpenGeneric(
    typeof(IHandler<>),
    AppDomain.CurrentDomain.GetAssemblies());
container.Register(AllTypes.From( 
    AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(a => a.GetExportedTypes()))
    .BasedOn(typeof(IHandler<>))
    .Unless(t => t.IsGenericTypeDefinition)
    .WithService.Select((_, baseTypes) =>
    { 
        return 
            from t in baseTypes
            where t.IsGenericType
            let td = t.GetGenericTypeDefinition()
            where td == typeof(IHandler<>)
            select t;
    })
    .Configure(c => c.LifeStyle.Transient));
var asm = typeof(IHandler<>).Assembly;

container.RegisterManyForOpenGeneric(
    typeof(IHandler<>),
    from type in asm.GetTypes()
    where !type.IsAbstract
    where type.Name.EndsWith("Handler")
    select type);
container.Register(AllTypes.From(
    from type in asm.GetTypes()
    where !type.IsAbstract
    where type.Name.EndsWith("Handler")
    select type)
    .BasedOn(typeof(IHandler<>))
    .WithService.Select((_, baseTypes) =>
    {
        return
            from t in baseTypes
            where t.IsGenericType
            let dt = t.GetGenericTypeDefinition()
            where dt == typeof(IHandler<>)
            select t;
    })
    .Configure(c => c.LifeStyle.Transient));
Mapping of open generic types to an open generic implementation
Simple Injector Castle Windsor
container.RegisterOpenGeneric(
    typeof(IValidator<>),
    typeof(NullValidator<>));
container.Register(Component
    .For(typeof(IValidator<>))
    .ImplementedBy(typeof(NullValidator<>)));

Last edited Oct 6, 2012 at 1:50 PM by dot_NET_Junkie, version 6