I discovered a nice feature in castle windsor yesterday (and a need for this feature).

Lets say you have the following classes:

public class TfsSourceControl : ISourceControl
{
  public TfsSourceControl(IRepositoryWebSvc websvc)
  {
    //...
  }
}

public class RepositoryWebSvc : IRepositoryWebSvc
{
  public class RepositoryWebSvc(IContext context, IFileCache cache)
  {
    //...
  }
}

The interface IContext represents in this scenario something that I want to pass in manually at the time of the component resolution, it could for example be a user context or some contextual settings, that is a dependency that cannot be automatically resolved. In Windsor you can pass in manual dependencies like this:

Hashtable arguments = new Hashtable();
arguments["context"] = myContext;
Container.Resolve<IRepositoryWebSvc>(arguments);

The code above will manually supply the dependency for IContext. What I did not know was that you can pass in arguments for sub dependencies as well, so this works:

Hashtable arguments = new Hashtable();
arguments["context"] = myContext;
Container.Resolve<ISourceControl>(arguments);

The dependency resolver in Windsor will carry with it the manual arguments for sub dependencies (as well as for sub-sub-etc dependencies). This enables you to request a top level component from windsor and pass in manual arguments that are needed by any component in the dependency tree. In the .NET 3.5 build of Castle Windsor you can use an anonymous type instead of a dictionary.

Container.Resolve<TfsSourceControl>(new {context = myContext});

Of course you should try to minimize the need to pass in manual arguments for dependencies, you want to utilize the auto dependency lookup as much as possible, but sometimes it can be very useful.

3 comments:

James said...

Thanks for that, was just what I was looking for...

timucin said...

It's not working on castle windsor 2.5.1 can you help me about issue? If i try to resolve ISourceControl windsor throw an exception like this 'failed: Castle.MicroKernel.Handlers.HandlerException : Can't create component 'context' as it has dependencies to be satisfied. '.

houstoncsusergroup said...

I'm new to using Windsor and IoC in general.

Do you know a way for the Windsor Resolve to call the default constructor on the type that you're resolving? Meaning, if I have a Foo and Resolving IFoo gives me Foo, instead of Windsor calling the resolve on the dependencies that are in the second constructor I'd like it to call the default constructor (which I then supply appropriate implementations for real integration and not unit testing).