Published: 30 Jul 2007
By: Simone Busoli
Download Sample Code

Since the previous article didn't show much of the features offered by Castle Windsor Container, I will resume the previous discussion extending the requirements of the former example to show how IoC deals with changes and what is its real potential.

In the previous article I introduced the concepts of Inversion of Control and Dependency Injection, and showed how to benefit from their use when developing a simple application. Although that naive example didn't take advantage of IoC and DI as much as a real life application would, it was meaningful in order to let developers new to these concepts start thinking in the right direction.

Inversion of Control/Dependency Injection Series

  • IOC/DI - Part I This article introduces Inversion of Control/Dependency Injection in a simple and affordable fashion, with a real example which evolves step by step to take advantage from IoC and DI, leveraging the features offered by an open source framework called Castle Project.
  • IOC/DI - Part II In the previous article I introduced the concepts of Inversion of Control and Dependency Injection, and showed how to benefit from their use when developing a simple application. In this article I will resume the previous discussion extending the requirements of the former example to show how IoC deals with changes and what is its real potential.
  • IoC/DI - Part III In this article I conclude the discussion about the core features of Windsor Container while evolving the simple example that accompanied you through the whole series of these articles. The next article will tackle more advanced topics.
  • IoC/DI - Part IV In this article I introduce the missing core features I didn't tackle before. They require a little more knowledge of Windsor, which I hope I've been able to hand down so far.
  • Introduction

    In the previous article I didn't show much of the features offered by Windsor Container. This time I'm going to introduce small incremental changes to the requirements of the sample application to show how Windsor can deal with them.

    So far, you've seen how you can instruct the container to retrieve and instantiate components, as well as resolve dependencies on the constructor. Here's what the signature of the constructor of the HtmlTitleRetriever class looked like:

    Therefore, the HtmlTitleRetriever class had dependencies on two references to objects implementing IFileDownloader and ITitleScraper interfaces (services) to be satisfied in order to be instantiated. With a canonical approach, you have to create these references and then supply them to the constructor. By using Windsor you could use the configuration file and resolve them in the following way:

    Constructor injection and compulsory dependencies

    When an instance of the HtmlTitleRetriever class was required using the snippet above, the container was able to infer that, in order to instantiate the class, it needed to supply its dependencies to the constructor. The instantiation was successful because those dependencies were satisfied by the other two components registered in the configuration file. If just one of them wasn't registered, the container wouldn't have been able to resolve them and would have thrown a Castle.MicroKernel.Handlers.HandlerException exception.

    As you may guess, the dependencies on the constructor are compulsory, because you can't instantiate an object if you don't supply all of them. The operation of resolving and supplying constructor dependencies is called constructor injection in terms of IoC, and it's one of two ways of supplying dependencies to components.

    You should rely on constructor injection whenever it makes sense for a component to compulsorily require a dependency in order to work. In other cases, you might want to provide a default implementation for a service or a general dependency, thus making it optional. This concept will make sense shortly.

    Setter injection and optional dependencies

    In order to illustrate how to deal with optional dependencies, let's make a small change in the requirements of the sample application. The GetTitle method of the HtmlTitleRetriever class should return a string containing the title of the HTML document supplied as input parameter (as before); but now prefixed by a descriptive message, which can be a custom or a default one. You can think of satisfying this requirement by introducing a property called AdditionalMessage with a backing field whose value defaults to Title:, which can be changed using the setter of the property. The changes are shown in the following snippet:

    Of course this change in the code of the class doesn't require any modifications to the configuration file of the container. The application will work fine since if no value is provided, the getter of the property will return the value set on the backing field during instantiation.

    Now, what if you want to change the default message returned by the GetTitle method along with the title of the document? Remember, the responsibility to instantiate the HtmlTitleRetriever class is no longer yours, but the container's.

    For this and other purposes Windsor offers a lot of configuration options, which I will try to illustrate in the remainder of this article and in the next one.

    Going back to the new requirement, you want to be able to supply a different value for the AdditionalMessage property; other than the default value hard coded in the class. This can be accomplished via configuration parameters for components, which can be specified in the configuration file.

    The snippet below shows how the configuration for the HtmlTitleRetriever component changes to satisfy the requirement, by setting the AdditionalMessage property to "This is the title of the document:".

    Notice the syntax used to specify the value of the property. Inside the component element you have inserted a child element called parameters, whose child is another element with the same name as the property you want to set. The mechanism of specifying dependencies by using properties is called setter injection.

    Differently from constructor injection, setter injection has to do with optional dependencies, since the only constrain which needs to be satisfied when instantiating an object is that all the parameters accepted by its constructor must be supplied. Optional dependencies, instead, don't prevent the container from instantiating the component. They are usually assigned a default value which can be changed by specifying a new value in the configuration.

    Another thing to note is that the syntax used above in the configuration file is valid for both setter and constructor injection. In this case, the constructor of the HtmlTitleRetriever class can be resolved automatically by the container because those are dependencies on other components registered in the configuration file. In case I make the dependency on the AdditionalMessage property compulsory by modifying the constructor and adding a third parameter of type string called additionalMessage, the syntax of the configuration file would be the same as above (the AdditionalMessage element in the xml file should be additionalMessage for coherence, to reflect the name of the parameter, but the container is case insensitive, so you can even write it all lowercase), with the only difference that this time the dependency would be compulsory. If not provided in the configuration file, an exception would be thrown by the container.

    Back to setter injection. Upon component request, Windsor realizes that you have specified a configuration parameter which maps to a property of the class endowed with a setter (hence setter injection) and thus assigns to the property the value you specified after an instance is created. Remember: If no value is specified in the configuration file, no operation would be performed by the container on the property, and the backing field would keep its default value. Therefore, to avoid incurring in null references or incoherent values, always give a default value to optional dependencies.

    Injecting components

    Now on to something more interesting. While reading the last paragraph, you may have noticed the difference between the string parameter/property dependency-that you could specify by giving it a value in the configuration file-and the dependencies on other components, like the ones the HtmlTitleRetriever class has on the IFileDownloader and ITitleScraper services. Suppose you need to retrieve files via the FTP protocol instead of HTTP. You'd need to create another class implementing the IFileDownloader interface and register it in the configuration file as a new component. Let's see how it's done:

    Now you might be asking: how do I switch from one implementation to the other? There's obviously a way to explicitly specify a particular component. In case of no explicit configuration and multiple components implementing the same service, Windsor should choose the first component registered in the configuration file.

    I said should because I noticed that there's a little subtlety (read, issue) that needs to be taken into account. At the time of writing, it looks like the expected first registered-first chosen behavior can be achieved only as long as the IDs of the components stay below the 8 characters in length. Otherwise, the choice seems unpredictable.

    This is a good reason to show you how to explicitly switch implementations at runtime using Windsor configuration. The syntax to accomplish this task differs from the one used to specify dependencies on explicit values like strings, numbers, dates and so on. Otherwise, the container would be unable to infer what you want to do. The syntax used to specify components as parameters uses the ${component id} format. Let's see an example. Having registered the FtpFileDownloader component, you can choose to use it when resolving the HtmlTitleRetriever class by simply adding a new configuration parameter to the HtmlTitleRetriever component, as shown in the following snippet.

    Notice how the new syntax is inserted in the parameters section just like you did before with a simple string parameter. Now you can switch between the two implementations of the IFileDownloader service just by referencing their IDs. The xml item is called downloader because it matches the name of the constructor parameter, like you did before with the AdditionalMessage property.

    Working with arrays, lists and dictionaries

    At the moment the HtmlTitleRetriever class is not very useful when it comes to downloading files with different protocols or stored in different locations. Each time you'd have to change the configuration file to reference a specific component for that protocol. Let's try resolving this issue.

    Note: actually, the WebClient class is able to retrieve files via FTP, so there would be no real need for a new class. The redundant class is implemented for educational purposes only.

    The HtmlTitleRetriever class should be able to deduce how the file supplied to the GetTitle method needs to be retrieved. It should be able to retrieve the file if it can rely on a component created for that purpose. In order to do this, let's first change the contract of the IFileDownloader service to provide a method called SupportsUriScheme.

    This method will need to be implemented by inheritors to return a Boolean values indicating if they are able to download a file with that specific schema. So here's how the HttpFileDownloader and FtpFileDownloader classes change.

    With this trick, each component providing the IFileDownloader service has knowledge about its capability to download a specific file. You will see shortly why this makes sense.

    Going back to our not-very-useful HtmlTitleRetriever class; in order to let it download files with different protocols it needs references to several implementations of the IFileDownloader service, each for a supported protocol/location. This can be accomplished in several ways; let's see how to supply multiple components using arrays. The constructor of the class now accepts an array of IFileDownloaders, as shown in the following snippet.

    The body of the GetTitle method has changed. Now it iterates through the array of downloaders and checks if it can find one suitable for downloading the file. Once it finds one, it downloads the file and scrapes the title as done before. If no suitable downloader is found, an empty string is returned. So far nothing new, but you need to change the configuration to let Windsor understand that you want the class populated with an array of downloaders. Here's how the configuration file takes advantage of this feature.

    The code is pretty simple to understand, so I will not delve deeper into it. As for the parameters element, the array element can accept any parameter-be it a string, Boolean, DateTime or a reference to a component. The only difference is in the syntax used to specify the component, which requires its ID surrounded by brackets and preceded by the dollar $ symbol.

    Just like arrays, you can pass lists and dictionaries to constructors and properties. The syntax is similar and is shown in the following snippets. The two snippets below show how to achieve the same result using lists instead of arrays.

    The following snippets show how to use dictionaries.

    Note that by using dictionaries I could have omitted the SupportsUriScheme method, since I could have specified the name of the supported protocol as the key of the dictionary entry and then retrieved it by key in the GetTitle method.

    Summary

    In this article you've seen how to deal with more sophisticated requirements using Windsor container configuration. In particular, I've talked about optional and compulsory dependencies, and how they map respectively to properties and constructors, as well as how to switch service implementations using a specific syntax offered by Windsor. Finally, I've given a quick overview of how to work with arrays, lists and dictionaries. In the next article I will talk about more configuration options and introduce advanced concepts like decorators and lifestyles.

    References

    <<  Previous Article Continue reading and see our next or previous articles Next Article >>

    About Simone Busoli

    Sorry, no bio is available

    This author has published 10 articles on DotNetSlackers. View other articles or the complete profile here.

    Other articles in this category


    Introduction to StructureMap
    Have you heard of StructureMap, generally know what it’s for, and want to know how to get started qu...
    DI Patterns: Constructor Injection
    In this article, an excerpt from the book "Dependency Injection in .NET", we will take a detailed lo...
    The Command Pattern
    In this article I will provide a quick refresher on what the command pattern is used for, how it wor...
    TypeMock’s Arrange-Act-Assert
    Brian Mains discusses how to implement the Arrange-Act-Assert pattern in TypeMock.
    Key Process Patterns
    This article, based on chapter 2 of Specification by Example, presents effective patterns for softwa...

    You might also be interested in the following related blog posts


    CodeDigest.Com Article,Codes,FAQs - April,2009 read more
    Delegating Decorators read more
    Party with Palermo @ DevTeach is tomorrow!! read more
    Rendering individual controls for AJAX Callbacks read more
    Silverlight 2 Beta 1 Controls Available, including Source and Unit Tests read more
    ASP.Net MVC Framework - Create your own IControllerFactory and use Spring.Net read more
    Application vs. AppDomain read more
    Custom Controls in ASP.NET (Part 1) read more
    Accessing and Updating Data in ASP.NET 2.0: Creating Custom Parameter Controls read more
    Atlas M2.2 - Dynamic UpdatePanels (finally) read more
    Top
     
     
     

    Discussion


    Subject Author Date
    placeholder how to retrieve downloader based on dictionary key Job Lot 6/25/2009 2:52 AM
    RE: how to retrieve downloader based on dictionary key Simone Busoli 6/25/2009 5:47 PM

    Please login to rate or to leave a comment.