6

Okay, so here's how I understand IoC and DI in Web API to work when using Castle Windsor.

Note, though, that my confidence that I understand it as I should, though, falls somewhere between my confidence I could best Dennis Rodman in a one-on-one basketball game and my confidence in his sanity.

Another way to put it is to say that I have spent the last several days reading up on IoC/DI/Castle Windsor with Web API and experimenting with it, but I still feel like wearily responding, "All down but nine, pard; set 'em up on the other alley."

I have several more specific questions on Stack Overflow about it, such as this one, but am not yet much clearer about it.

So I'm going to "talk out loud" and hope that somebody responds with something that will refine my understanding, shed some light on this opaque (to me) subject, or help unravel this Gordian knot.

Point: The basis of IoC/DI lies in passing interfaces to constructors, so that the class with the constructor does not have to instantiate its own objects; in fact, has no need to know the concrete component/class.

Point: To set this up, you need code like so in your Controllers:

private readonly IDepartmentRepository _deptsRepository;

public DepartmentsController(IDepartmentRepository deptsRepository)
{
    if (deptsRepository == null)
    {
        throw new ArgumentNullException("deptsRepository is null");
    }
    _deptsRepository = deptsRepository;
}

Point: Some class that implements IDepartmentRepository is passed to the DepartmentsController constructor

Point: The coder doesn't do that explicitly - the IOC container (Castle Windsor, in this case) does that "automatically" by intercepting the Web API routing mechanism with its own, as with code like this, in global.asax.cs:

GlobalConfiguration.Configuration.Services.Replace(
                typeof(IHttpControllerActivator), new WindsorCompositionRoot(_container));

Point: global.asax.cs' Application_Start() gets the ball rolling and calls the Installer/Registrar with code such as:

protected void Application_Start()
{            
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    ConfigureWindsor(GlobalConfiguration.Configuration);
}

public static void ConfigureWindsor(HttpConfiguration configuration)
{
    _container = new WindsorContainer();
    _container.Install(FromAssembly.This());
    _container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel, true));
    var dependencyResolver = new WindsorDependencyResolver(_container);
    configuration.DependencyResolver = dependencyResolver;
}   

Point: Lots of other Castle Windsor scaffolding has to be set up for this. Specifically, classes need to be "installed" (registered - I think registered would have been a better/more easily grokkable term for it).

This is one of my major "say what?"/headscratching areas. I don't know if that registration code should look like this:

public object GetService(Type serviceType)
{
    return _container.Kernel.HasComponent(serviceType) ? _container.Resolve(serviceType) : null;
}

public IEnumerable<object> GetServices(Type serviceType)
{
    if (!_container.Kernel.HasComponent(serviceType))
    {
        return new object[0];
    }

    return _container.ResolveAll(serviceType).Cast<object>();
}

...or like this:

public class ApiControllersInstaller : IWindsorInstaller
{
    public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly() // should it be Types instead of Classes?
         .BasedOn<ApiController>()
         .LifestylePerWebRequest());
    }
}

...or like this:

public class ServiceInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<IDeliveryItemRepository>().ImplementedBy<DeliveryItemRepository>().LifestylePerWebRequest(),
            Component.For<IDeliveryRepository>().ImplementedBy<DeliveryRepository>().LifestylePerWebRequest(),
            Component.For<IDepartmentRepository>().ImplementedBy<DepartmentRepository>().LifestylePerWebRequest(),
            Component.For<IExpenseRepository>().ImplementedBy<ExpenseRepository>().LifestylePerWebRequest(),
            Component.For<IInventoryItemRepository>().ImplementedBy<InventoryItemRepository>().LifestylePerWebRequest(),
            Component.For<IInventoryRepository>().ImplementedBy<InventoryRepository>().LifestylePerWebRequest(),
            Component.For<IItemGroupRepository>().ImplementedBy<ItemGroupRepository>().LifestylePerWebRequest());
    }
}

...or elsewise...

Point: Once all this is set up, and the Controllers (and Repositories? Is there more that do I have to about them, to make them safe for CW?) have been registered by the Castle Windsor routing engine, a call to my Web API app like:

http://platypus:28642/api/Departments

...will be resolved to a "component" (concrete class) that implements IDepartmentRepository. CW will be able to figure that out, as long as I have one class that implements IDepartmentRepository, that that is the one to silently pass to the Controller's constructor which takes an arg for a class that implements IDepartmentRepository.

But...what if there are are N classes that implement IDepartmentRepository? How does CW know which one to pass to the Controller's constructor? How can I, the lowly human in this meeting of silicon and pink squishy stuff, designate which of the N I want CW to pass to the constructor?

  • "confidence I could best Dennis Rodman in a one-on-one basketball game and my confidence in his sanity." I'd put both close to 0. :-) – Ross Patterson Jan 9 '14 at 12:41
  • That was my point. An insanity "plea: is his best bet; if he is sane, he's evil/a jerque. – B. Clay Shannon Jan 9 '14 at 16:50
  • "plea" not "plea: – B. Clay Shannon Jan 9 '14 at 17:26
  • 1
    Another small comment. You can use DI with concrete classes, injection around interfaces is not a must. Usually you do get there due to unit testing concerns, but sometimes setting up a concrete class and have the container deal with it's dependencies for you can be convenient. – Joppe Apr 3 '16 at 13:40
  • 1
    you can use any of those methods. BUT you are writing in a MS language for an MS server. why not use the MS DI container, unity – Ewan Apr 4 '16 at 15:56
9
+100

I have experience with Ninject, not Castle Windsor, but the principles should be the same.

To understand dependency injection, it helps to recall how you wrote code without it. Typically, the DepartmentsController constructor would look like something like this:

public DepartmentsController()
{
    _repository = new DepartmentRepository();
}

The controller depends on the repository, and by placing it in the constructor we ensure that every DepartmentsController is instantiated with a repository and begins its life in a valid state. By doing this, however, we make it more difficult to later swap one implementation of DepartmentRepository for another. In particular, if we want to isolate the DepartmentsController and test it independently, we're in trouble. How do we test this class without invoking actual calls to the database through DepartmentRepository?

Your first example improves on this scenario by creating a "seam" between the objects: a point where the two are glued or stitched together that can be separated easily, especially for tests. Instead of creating the DepartmentRepository itself, your controller can ask for it:

public object GetService(Type serviceType)
{
    return _container.Kernel.HasComponent(serviceType) ? _container.Resolve(serviceType) : null;
}

This is called the Service Locator pattern, and some consider it bad practice. By exposing Castle Windsor in this way, you have actually lost some of its benefits. In particular, your DepartmentsController now depends on the Service Locator and its GetService method. I won't cover all of the supposed disadvantages of Service Locators, but consider what happens when your application grows and you now have numerous classes (potentially all of them) dependent upon this single class.

Your third example improves upon the Service Locator pattern by making the container invisible to your class:

public DepartmentsController(IDepartmentRepository repository)
{
    if (repository == null)
        throw new ArgumentNullException("repository");

    _repository = repository;
}

Notice how this version has no knowledge of the kernel / container or a service locator. Instead, we have made its true dependencies explicit in the constructor rather than the means to those dependencies. In fact, by writing your classes this way, you can construct entire class libraries that are ignorant of Castle Windsor and will work perfectly fine with Ninject, another DI framework, or no container at all, without modifying the code.

How you actually register your components (the difference between examples two and three) is partly a matter of scale.

container.Register(
        Component.For<IDeliveryItemRepository>().ImplementedBy<DeliveryItemRepository>().LifestylePerWebRequest(),
        Component.For<IDeliveryRepository>().ImplementedBy<DeliveryRepository>().LifestylePerWebRequest(),
        Component.For<IDepartmentRepository>().ImplementedBy<DepartmentRepository>().LifestylePerWebRequest(),
...

is fine for a smaller application. If the number of classes grows, you have to stomach a never ending list of bindings or find a better method. One improvement is to favor convention over configuration: if Castle Windor assumes every IDeliverItemRepository has a DeliveryItemRepository implementation, the bindings above can be skipped. However, you haven't solved anything if most of your classes require exceptional configuration; you still have a long, omniscient kernel / container registration method.

Instead, you should probably explore something like your second example. This way, your ConfigureWindsor method can use reflection to find any IWindsorInstallers present in your application without knowing about specific interfaces or implementations. You can break all of your bindings into separate modules (Ninject's name for this concept) that are discovered at runtime.

To address your last question: Castle Windsor won't know which of your N implementations to choose without you telling it. You can accomplish this through a mixture of the concepts discussed above: primarily by convention, but with IWindsorInstallers when needed to specify important details like lifecycle and conditional bindings.

  • So how do you tell Castle Windsor: For now, use this concrete class instead of that one? Is it a matter of temporarily commenting out the implementation that you don't want to be used, or...??? – B. Clay Shannon Jan 9 '14 at 18:03
  • 1
    If you only have one implementation to be used at a time, I would say delete the old binding and create a new one. If you're worried about somehow losing the old binding, it should be in your source control system. If you want multiple implementations working at the same time, you'll need to specify conditional bindings. See the link I posted at the end of my answer. – Joshua Dutton Jan 11 '14 at 21:21
  • Thanks; I'll czech that link again. I will want two always, a "test" one and the real one for each case. I want to easily switch between "use the test implementation" and "use the production implementation." If it's not easy to do that, the viability of DI and/or CW is reduced considerably; for me, anyway. – B. Clay Shannon Jan 13 '14 at 16:37
  • 1
    I'm not sure what you mean by "test implementation" unless you're referring to automates tests (unit tests), in which case CW should not be responsible for providing it. Instead, look at a mocking framework such as Moq. – Joshua Dutton Jan 13 '14 at 20:02
  • I would rather just be able to quickly "swap out" a test vs. a "real" (production) concrete class. – B. Clay Shannon Jan 13 '14 at 20:25
4

CW knows which on N classes implement IDepartmentRepository via reflection. It knows which one you want because you registered it - that's the point of registering. It's kind of smart though, it looks at the constructors of what you've registered and tries to deduce the concrete types based on what you have registered. So sometimes registering the top of a dependency tree will be enough to let it figure out the rest.

There are multiple ways to register, for your convenience (and confusion). Using a fluent API for your convenience (and confusion). You also can control things about the life-cycle of dependencies (imagine a dependency needs to call dispose(), but the class getting the dependency didn't create it and can't know about it's life cycle - a more advanced topic though).

You should register the concrete classes you want, then resolve them in your Main method (in your case Application_Start serves this purpose), this will create all your objects in the dependency graph right away. Call release on the container when you are done. Don't call the container anywhere else in the app.

I hope that helps - there were a lot of questions.

I personally liked Dependency Injection in .NET as a reference (no affiliation with me), but it isn't free.

  • Great suggestion on the book; I read part of it online (amazon), got to the roadblock of key pages deliberately missing, and then found that we have the .PDF here at work! That book is gr8! – B. Clay Shannon Jan 9 '14 at 19:23
  • I would add that you should only call Resolve once on the top level class of the application (think Program class). An exception to this rule is MVC Controllers, because different controllers may act as the "top level class" depending on the url requested. – reggaeguitar Feb 10 '16 at 22:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.