C# Corner

Windsor: Beyond Dependency Injection in WPF

Dig deeper into the Castle Windsor IoC container by learning how to control dependencies.

In my October column, I discussed how to use Inversion of Control (IoC) containers to decouple Views and ViewModels in Windows Presentation Foundation. In this article, I'll go beyond the basic registering and resolving of components in the Castle Windsor IoC container and into controlling what dependencies get resolved, how to override default dependencies and even integrate with components not registered in the container.

Dependency Injection with Windsor
I've used Dependency Injection (DI) in a number of my columns. My container of choice is Castle Windsor. While Windsor makes IoC easy, there have been a few occasions where I've needed to push things a little farther. Windsor's extensibility has made this much easier. I'll explore a few cases in which I've plugged into Windsor to make my experience with the container, as well as my overall application logic, easier to manage.

Sub-Dependency Resolver
Part of the beauty of an IoC container is that it automatically resolves dependencies for you. For example, imagine the following class definitions:

public class Bar
{
  public Bar(IFoo foo)
  {
  }
}

As long as both Bar and an implementation of IFoo are registered in the container, all you need to do is ask the container for an instance of Bar. The container will find the IFoo needed to call Bar's constructor automatically. This comes in really handy when the IFoo implementation also has dependencies registered in the container.

But there are times when you can't register a class dependency in the container. Think about a database connection string. The string could come from a number of places: a web.config file, perhaps encrypted inside the Registry, or even stored in a local text file (not very secure, but I've seen it before in legacy systems!).

The point: You want to create a component that relies on a connection string. You don't want to write a component that decrypts some Registry entry. And you don't want to have to create a wrapper around the ConfigurationManager object just for this connection string. You want to honor the Keep It Simple, Stupid! principle and simply define your component as:

public class FooRepository
{
  public FooRepository(string connectionString)
  {
    // ...
  }
}

To further complicate things, your component will need to know the component at the time it's resolved, not at the time it's registered. Providing a single connection string at registration time is simple with Windsor (and probably every other IoC container out there). When you want to exert some influence in how Windsor will resolve dependencies, you can create your own sub dependency resolver.

To show what a sub dependency resolver can do, I'll create one that will resolve any string parameter to an application setting defined in the configuration file (either app.config or web.config). The first thing I do is create a class that implements ISubDependencyResolver, shown in Listing 1.

The first method, CanResolve, lets Windsor know whether this resolver can handle a specific type of dependency. In my case, I only want to handle dependency parameters that are of type string. This is accomplished with:

public bool CanResolve(CreationContext context,
  ISubDependencyResolver contextHandlerResolver,
  ComponentModel model,
  DependencyModel dependency)
{
  return dependency.DependencyType == DependencyType.Parameter
    && dependency.TargetType == typeof(String);
}

The second method, Resolve, will only be called if CanResolve returns true. When called, I need to tell Windsor how to resolve the component. In this case, I want to pull out whatever data's available in the application's configuration file, based on the name of the parameter (Windsor exposes the parameter's name through the DependencyKey property):

public object Resolve(CreationContext context,
  ISubDependencyResolver contextHandlerResolver,
  ComponentModel model,
  DependencyModel dependency)
{
  return ConfigurationManager.AppSettings[dependency.DependencyKey];
}

Here's a quick example showing how this would get registered in Windsor:

var container = new WindsorContainer();
container.Kernel.Resolver.AddSubResolver(new AppConfigResolver());
container.Register(
  Component.For<FooRepository>().LifeStyle.Is(LifestyleType.Transient));
 
var repository = container.Resolve<FooRepository>();

When Windsor resolves the FooRepository, the AppConfigResolver will be asked to resolve the "connectionString" argument in the constructor. Our custom resolver will then return whatever value is in the "connectionString" appSetting in the configuration file.

Note that I added my custom resolver before I registered my component in the container. If you forget to do this, your custom resolver won't be used during component resolution. While this is a trivial example, it shows how easily you can tweak the way Windsor resolves dependencies.

Service Overrides
There are times when you may want a component to have a dependency on certain implementation. Imagine you have six components that all rely on an IFoo implementation. Then you run in to a situation where one of those six needs a slightly different IFoo. Windsor supports registering multiple implementations of IFoo, but if all six components have a dependency on IFoo, which IFoo will Windsor use when resolving?

The answer: The first one registered. This, of course, does me no good in a situation where I need one component to use a different IFoo than the rest of the components. Assume I have the following registration (components Boo, Bar and Baz all have a dependency on IFoo):

var container = new WindsorContainer();
container.Register(
  Component.For<IFoo>().ImplementedBy<Foo>(),
  Component.For<IFoo>().ImplementedBy<SpecialFoo>(),
  Component.For<Boo>(),
  Component.For<Bar>(),
  Component.For<Baz>()
);

Whenever I ask for a Boo, Bar or Baz instance, they'll all get the Foo implementation of IFoo because it was the first one registered. What I want to do is specify which implementation of IFoo to use for the edge case of a special requirement.

This is where a service override comes in. Service Overrides in Windsor override Windsor's decision on which service implementation to provide for a dependency. The first step is to name my implementations with a key designator:

container.Register(
  Component.For<IFoo>().ImplementedBy<Foo>().Named("foo"),
  Component.For<IFoo>().ImplementedBy<SpecialFoo>().Named("special"),
  Component.For<Boo>(),
  Component.For<Bar>(),
  Component.For<Baz>()
);

By "naming" specific implementations, I can use those names later on when registering the various components. For component "Baz," I want to use the SpecialFoo implementation, like so:

container.Register(
  Component.For<IFoo>().ImplementedBy<Foo>().Named("foo"),
  Component.For<IFoo>().ImplementedBy<SpecialFoo>().Named("special"),
  Component.For<Boo>(),
  Component.For<Bar>(),
  Component.For<Baz>().ServiceOverrides(
    ServiceOverride.ForKey<IFoo>().Eq("special"))
);

By using the "ServiceOverrides" option during component registration, I'm able to instruct Windsor to use a different implementation of IFoo. Why don't I define a ServiceOverride on Boo and Bar to use "foo"? Because I don't need to. Remember, Windsor will default to using the first registered component. Also, you can define a service override by either the name of the parameter or the type of parameter. I prefer doing it by type because the name of the parameter could change, and unless you remember to change your container registration code, your override won't work.

Typed Factory Facility
One of the common questions about using Castle Windsor is how to do delayed ("lazy") resolution of components. In this scenario, I want a component resolved at the moment used, not the component that was resolved through dependency injection during construction of the class. In these cases, I've seen people ask questions about how they should pass around a reference to the container so that they can call container.Resolve<> right when they need it. The simple answer is, "you don't pass the container around." Instead, you would utilize a factory.

I did a series a while back on the factory pattern. I even touched on Windsor's Typed Factory Facility. The Typed Factory Facility allows you to define just the interface for your factory. The implementation will be done automatically by Windsor at runtime. Here's an example:

public interface IFormatter
 {
  string FormatData(string data);
}
 
 public interface IFormatterFactory
{
  IFormatter GetFormatter();
 }

Whenever I need an IFormatter, I won't pass around a reference to my container. Instead, I'll add the Typed Factory Facility to Windsor and then add the IFormatterFactory to Windsor with the AsFactory extension method:

var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
  Component.For<IFormatterFactory>().AsFactory()
);

I'll use this interface just as I would use any other component registered in Windsor, except I won't need to write the implementation -- Windsor will handle it for me. Any component that needs to create an IFormatter will have a dependency on IFormatterFactory:

public class MyComponent
{
  private IFormatterFactory factory;
 
  public MyComponent(IFormatterFactory factory)
  {
    this.factory = factory;
  }
 
  public void DoSomething()
  {
    var formatter = factory.GetFormatter();
  }
 }

So how does Windsor do this magic? It's actually quite simple. Windsor intercepts all calls to the factory interface. When a method of the factory is called, Windsor has some default handling to figure out what to return:

  • If the factory method called returns any type of "list" of components (such as IFoo[] or IEnumerable<Foo>), Windsor will return all registered components of that type. The name of the factory method in this case is totally meaningless.
  • If the factory method called returns a specific type and starts with "Get", the rest of the method name (after the "Get") is assumed to be the component name and Windsor returns the first component registered with that name and matching type. In the case of a factory method called "GetDiscountCalculator," Windsor will return the component named "discountcalculator" (component names in Windsor aren't case-sensitive).
  • If the factory method doesn't start with "Get," Windsor simply looks at the return type and returns the first registered component of that return type.

The Windsor Typed Factory Facility makes lazy component resolution much easier. There's no need to implement the actual factory interface, and the resulting code is much better than passing around a reference to the container or, even worse, utilizing the ServiceLocator pattern.

Handler Selectors
Handler Selectors let you control which handler Windsor will use to resolve a component. They're similar to service overrides, but are context-sensitive. You can create a custom handler selector and it will be evaluated at runtime when your application needs to resolve a component. This allows you to take current application state into account and make changes to component resolution.

A simple example is a case where I needed to poll a REST feed for data. The application doing the polling was important and had to keep running, even if the network connection went down. I created a caching mechanism that saved the last set of data locally to the hard drive. I then created two components: one that pulled data from the REST feed and one that pulled the data from the hard drive if the network connection was down. However, I still needed to have Windsor resolve a specific one depending on the network state.

This is where the Windsor Handler Selectors made things much easier for me. I started with a simple interface for pulling my data:

public interface IDataFeed
{
  string GetData();
}

I then implemented two types of IDataFeed, as shown in Listing 2: one that used the REST feed and one that pulled the cached results locally (implementation details are omitted for this example).

Now I just needed to make a Handler Selector that would select the appropriate IDataFeed based on network availability (see Listing 3).

The IHandlerSelector is a simple interface. Like the sub dependency resolver I discussed earlier, the IHandlerSelector interface exposes its willingness to participate in the component resolution process by returning true or false for "HasOpinionAbout." For my application, I'm only interested in controlling resolution of IDataFeed objects:

public bool HasOpinionAbout(string key, Type service)
{
  return service == typeof(IDataFeed);
}

If the handler returns true for this method, the SelectHandler method will be called, as shown in Listing 4. The entire list of handlers for the particular type is passed to this method. This is where I'm able to make the choice about which component to use.

When registering my components, I have to add my custom handler selector to the container, as shown here:

 var container = new WindsorContainer();
  container.Kernel.AddHandlerSelector(new DataFeedHandlerSelector());
container.Register(
  Component.For<IDataFeed>()
    .ImplementedBy<RestDataFeed>()
    .LifeStyle.Is(LifestyleType.Transient),
  Component.For<IDataFeed>()
    .ImplementedBy<LocalDataFeed>()
    .LifeStyle.Is(LifestyleType.Transient)
);

With my custom handler selector in place, my components are free to simply have a dependency on IDataFeed, and they'll get the correct one based on network availability. I don't need to pollute my application code with the details of which component to use.

Also notice that the handler selector is created via "new"; that is, we're not using the container. This is one of those rare cases where you might need to pass the container to the handler selector. By doing so, the handler selector can pull additional components/dependencies from the container using container.Resolve.

Lazy Component Loader
Windsor supports resolving of components not even registered in the container. What? Why would you want such a thing? To be honest, it's not something you're going to use that often. Most of the techniques described in this article, such as service overrides or handler selectors, are better suited to dynamic resolution. However, it can work in the cases where the types can't be registered in the container at application startup.

The few times I've used the lazy component loader, it's been during code sprints where I'm still unsure of the exact direction I'm going to be taking with my container usage. Will I be using service overrides? Or maybe handler selectors? Until I've nailed down a design, a lazy component loader lets me resolve my components through Windsor without much setup.

Creating a lazy component loader is as simple as implementing the interface ILazyComponentLoader. Add the loader to the container just like any other component -- there's nothing special about it. Whenever Windsor encounters a component that isn't registered, it will ask any registered ILazyComponentLoader to try and register the component.

Here's a basic example where any component with a name that starts with "Lazy" will be automatically registered in Windsor the first time it's requested:

public class RegisterAllLazyComponents : ILazyComponentLoader
{
  public IRegistration Load(string key, Type service, IDictionary arguments)
  {
    if (service.Name.StartsWith("Lazy"))
    {
      return Component.For(service);
  }
 
    return null;
  }
}

As noted earlier, there aren't too many cases where this will be useful. Your use of Windsor will be much cleaner if you register the necessary components up front. One place lazy loading comes into play is with Windows Communication Foundation (WCF) configuration files. Castle Windsor comes with a WCF facility that takes advantage of the ILazyComponentLoader to handle service definitions in external configuration files.

You should take note that ILazyComponentLoader is only called once per type. Even if the type's a transient, the ILazyComponentLoader is only called the first time a type's found that doesn't exist in the container. The loader's only two options are to do nothing or to register the component (register -- not resolve).

Extensibility with Castle Windsor
I hope this column has opened your eyes to the amazing possibilities for extensibility with the Castle Windsor IoC container. These techniques can help you write more robust code and have a cleaner integration with the container. If there are other features of Castle Windsor you're interested in, feel free to drop me an e-mail.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube