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.
In case you didn't read the previous parts I highly suggest doing so. The sample application I used to illustrate the framework has been developed step by step since the beginning.
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.
As usual, any feedback, questions and votes are very welcome, but now on to the nitty-gritty.
So far I haven't delved much into discussing the way components are instantiated and released. Actually, retrieving them from the container using
IWindsorContainer.Resolve and releasing them using
IWindsorContainer.Release doesn't necessarily mean that they are first instantiated and then disposed of by setting the reference (obtained with the
Resolve method call) to
Instead, the default behavior supplied by the container is called singleton, which means that upon the first call to
Resolve the component in instantiated by calling the class constructor that best matches the supplied dependencies as defined in the configuration file. Then all subsequent calls just return a reference to the same object in memory. In other words, the component behavior is that defined by the Singleton pattern, which means that a single instance of it is alive in the application domain, which is cached and returned at each request forwarded to the container. By default, calls to the
Release method don't have any effect on the component. This makes sense since a singleton object shouldn't be garbage collected as long as the application is running.
In Windsor Container, the way components are resolved and released is called lifestyle. In the sample application, as a consequence, all the components are given the default singleton lifestyle, since no additional configuration is supplied. However, Windsor offers several other lifestyles to choose from, as well as an API to create your own custom lifestyle.
The built-in lifestyles offered by Windsor Container are illustrated in the following table, along with the actions performed by the
Table 1: Built-in lifestyles offered by Windsor Container
first call instantiates the class and
returns a reference to it, subsequent calls return references to the same object.
call creates and returns a reference to a new object.
single instance is created per thread and then cached. Each thread owns a single
instance of a component.
instances are retrieved from a pool as long as it contains any, otherwise they are
are pushed back into the pool and made available for subsequent requests until the
pool is full, thrashed away otherwise.
Switching lifestyles can either be accomplished programmatically via attributes or declaratively using the configuration file. For example, the transient lifestyle can be applied to a component in one of either ways shown in the following snippets.
Lifestyles are very useful and pretty straightforward to understand. The Pooled style needs some explanation, since it requires a little more work on the configuration. It accepts two more configuration parameters which indicate the initial and maximum size of the pool, as shown below.
Note: As for the other lifestyles you only need to specify the lifestyle using one of the two methods, either attributes or configuration files.
Furthermore, its behavior intrinsically deviates from the standard behavior, since the pool is filled to its initial size as soon as the container in instantiated - before any instance of a component is ever requested. In other words, when the container is instantiated, a number of any pooled components equal to the respective initial pool size configuration parameter are immediately created. Requests of those components made to the container are satisfied by the pool, with no additional overhead introduced by just-in-time instantiation. Once the number of requests exceeds the initial pool size, new instances are created. On the other side of the lifestyle, upon release, component references are returned back to the pool and made available to satisfy subsequent requests made to the container, until the pool size reaches its maximum value. Subsequent releases are simply discarded by the container, as if those components didn't belong to the pool.
Note: The lifestyle of a component can be influenced by other configuration options exposed by the container. They will be discussed in the following sections.
To illustrate how lifestyles influence the behavior of components, let's edit the body of the main method of the sample application to request two references to a component and print out the hash code of their pointed object.
If the default singleton lifestyle is used, the two hash codes are equal, since two references to the same
HtmlTitleRetriever singleton object are returned. If the class is made transient, then the program will output different hash codes, since a new instance is created at each request.
In addition to the built-in lifestyles Windsor exposes a public API to create custom ones. To do so you need to implement the
ILifestyleManager interface and inform the container that you want to use it instead of the built-in managers. The most straightforward way of creating a new lifestyle, however, is to inherit from the
AbstractLifestyleManager abstract class, which already provides some support for common operations performed by all lifestyle managers. A sample custom lifestyle can be found at this page in the Windsor documentation.
Note: Lifestyles different from the default singleton didn't find any use in the sample application, so this part is not implemented in any of the components of the attached code.
Extending the container: Facilities
So far I've illustrated most of the features offered by Windsor Container, either basic and advanced ones. However, you may have noticed that they are naive features, in that they supply extremely simple services, although they carry them out in a very smart way.
Now, what if you wanted the container to supply a custom feature which is not provided out of the box? There are several options; you would either fill a feature request to the project's developers, create the feature on your own by changing the source code of the container or subclass the container and work with your custom container (as I did to support type conversion for Uri properties). All of this if Windsor didn't provide an extension mechanism called Facilities.
Note: Actually, facilities are part of the MicroKernel, although I'll employ them at Windsor Container level mostly using configuration files.
Following is the definition of facilities as given in the official documentation:
Facilities augment the MicroKernel capabilities by integrating it with a different project or technology, or by implementing new semantics.
Facilities can be grouped into three categories, as shown in the following table.
Table 2: Facilities
support for integration with other frameworks and projects, like NHibernate and
support for services built into CastleProject. Services are just a means to carry
out common tasks using a standard API.
the features of the container by supplying new semantics for component configuration
I will narrow the discussion to semantic facilities only, since they are intrinsically related to the container and don't interact with external services or frameworks.
A list of all the facilities supported by the MicroKernel can be found at this page
in the documentation.
The following sections will take advantage of two semantic facilities in order to respond to additional requisites for the sample application.
Now let's move on to something more interesting. The new requirement is that the sample application needs to be able to retrieve files via the HTTPS protocol as well. Actually, the
WebClient class provided by the .NET Framework is able to handle it; but in a real project the new requirement would involve some more work.
Suppose that the handling of the HTTPS protocol would require a lot of work, and that somehow you already own a class which provides this service. Luckily - although very unlikely in a real world case - this class, called
HttpsFileDownloader, already implements the
IFileDownloader interface. As a consequence, it can be registered together with the other file downloaders in the configuration file; and supply the same service. Unfortunately, it doesn't supply a public constructor, but instead just a static method called
Create which is the only public access point for creating instances of the class. Furthermore, you don't own the source code, but just a compiled assembly, so there's no straightforward way to circumvent the constraint imposed by the absence of a public constructor, which is needed by Windsor to instantiate components.
Figure 1: HttpsFileDownloader class diagram
One of the facilities supplied by the MicroKernel is called FactorySupport facility. Its name comes from the FactoryMethod design pattern. The facility provides a means of instantiating components without using their constructor, which is the default route.
In order to use any facility together with Windsor, it first needs to be registered in the configuration file as shown in the following snippet.
By registering the FactorySupport facility you have indirectly extended the container with a full new API which lets you use a new syntax to configure components and benefit from the facility. As shown in Figure 1, everyone who needs an instance of the
HttpsFileDownloader class needs to call the
Create method, which is the only method capable of calling the private constructor of the class. So how do you instruct the container that in order to instantiate that component it needs to perform these steps?
If the component is registered as is, upon resolution an exception of type
ComponentActivatorException is raised, since no accessible constructor was found. The FactorySupport facility, instead, provides you with a new syntax which lets you specify the class responsible of instantiating a component as well as the name of the method to call on that class. The following configuration snippet shows how to benefit from the new configuration options provided by the facility.
You can see that the configuration of the component has gained two new parameters,
factoryCreate. The first is the ID of the component supplying the factory method, while the second is the name of the method to call. In this case, the class exposing the factory method is the same as the class which needs to be instantiated, but you may even split up the responsibilities in two different classes.
Note that this is working because the factory method is static. If it was an instance method the container wouldn't be able to instantiate the component because a circular dependency would exist.
The snippet below shows the source code of the
With these simple steps you have instructed the container to call the
Create method in order to instantiate the component. For the rest, the component behaves just like any other.
The other semantic facility I'm going to talk about is the Startable facility. To understand what it can be used for let's introduce a new requirement to the sample application. So far, once the
HtmlTitleRetriever class was requested to the container, you had explicitly asked it to retrieve the titles of the files using the
GetTitles method. This entails that each time you have to wait for it to complete the download and the parsing before continuing the execution of the program. What about taking advantage of multithreading to accomplish this task so that you don't have to block the UI? And what about doing it implicitly - that is, as soon as the application starts and then at regular intervals - so that the waiting time can be virtually reduced to zero?
This may sound weird, but I'll show what I mean very soon. The idea is to make the
HtmlTitleRetriever class startable, so that it begins retrieving titles as soon as the application starts, and without blocking the user interface. I'll accomplish this using the
The Startable facility lets you benefit from a new semantic to start and stop components. This means that components made startable are instantiated and "started" as soon as possible when the application begins; and then "stopped" when they are released or when the container is disposed.
As with any facilities, the first step is to register it in the configuration file, as follows.
To make a component startable you can either implement the
IStartable interface or use the configuration file. The
IStartable interface contract exposes two methods, called
Stop, as shown below.
Taking the configuration route lets you optionally set the method names to start and stop your component, as shown in the two following snippets.
Now, let's implement the new requirement in the
HtmlTitleRetriever class and delegate the startable facility the task of starting and stopping it. As stated above, I'll use a timer to do the work of downloading and scraping the titles asynchronously on a thread supplied by the CLR thread pool. The code of the edited
HtmlTitleRetriever class is shown below.
Stop methods respectively start and stop a timer which executes a new callback method called
GetTitles(object). This method simply retrieves the titles of the files stored in the
Files property and caches them into a list so that they can be returned upon request without re-downloading them. Synchronization is required since access to the list may occur on different threads.
Another change has been introduced in the
GetTitles() method. Before, it didn't take any arguments. Now a Boolean value is required, which is used to specify if you want to retrieve the values cached in the list or force a new download. The code has changed quite a bit, so take the time to look at it and make sense of what it does.
No additional configuration is needed for Windsor to be able to manage the component correctly. By making it startable, the
HtmlTitleRetriever component is no longer instantiated when explicitly requested. Instead, it is created upon container instantiation, and the start method is immediately called. Thereby, even before the first request to be resolved, it has already been created and started; and hopefully it has already finished downloading files. Below is the code with the changes made to the sample application.
As highlighted in the code snippet above, the component is instantiated during container creation. What might not be completely intuitive is when it gets released. That is, when its
Stop method gets called. You may think that this occurs during the call to the container's
Release method. Actually, this happens during container disposal.
This is more intuitive if you think in terms of component lifestyle. I kept the default singleton lifestyle, therefore a single instance of the component is created in the
AppDomain of the application. When you release it using the
Release method, no action is performed because the component might still be requested again or might have other references active; it mustn't be neither stopped nor disposed. Only when the container itself is disposed then the component can be stopped too, because no one else will ever require it again. This behavior might change if the component had a different lifestyle. I will talk about release policy shortly.
In addition to those discussed earlier, Windsor provides several other ready-to-use facilities, either semantic, integration and based on services. They all can be useful during the development of a real project, in particular those which ease integration with external frameworks, like NHibernate or ActiveRecord. I didn't cover them during this series since they would require a more articulated example that would entail cooperation with a storage system. I can say that they make working with those frameworks a lot easier than it would be otherwise.
One facility based on services which is worth mentioning is the Logging facility. It makes integrating logging services in classes a breeze, along with the decorator pattern, as discusses in the previous articles.
Lifecycles provide a means of customizing the tasks performed by the container upon component creation and destruction. They can be grouped in two categories, using Castle official terminology: commission and decommission. Commission tasks are performed right after the component is created - in most cases when its constructor is called and optional dependencies have been injected. Decommission tasks are executed upon component disposal.
As explained before, the disposal of a component doesn't necessarily occur when the
Release method is called, but it depends on its lifestyle. To clarify: If a component is transient, its disposal - and thus the decommission tasks - are performed when the
Release method is called on the container. If the component is a singleton, it's not disposed when the
Release method is called; it happens when the
Dispose method is called on the container. As stated before, this makes sense because a singleton component may have other references still active and shouldn't be destroyed until all those references become inactive. This, in turn, can be ensured only when the container is disposed.
The means by which you can execute custom code during commission and decommission is via interfaces. The MicroKernel supports two interfaces; one for commission and one for decommission, as shown in the following table.
Table 3: Interfaces for commission and decommission
By implementing these interfaces you can be sure that the methods they expose will be called by the container at the right time, depending on the lifestyle of the component.
In practice, this appears much useful than it seems in words. Suppose you have a class which should dispose managed and/or unmanaged resources when garbage collected. How does Windsor know that it should call its
Dispose method? You can see that lifecycles is just a bright way to say that the container is smart enough to guess that if your class implements those interfaces, then it should call their methods at the right time, just as you would do if you didn't uptake IoC.
Let's see how to benefit from this feature in the sample application. As from the last edit to the code, the
HtmlTitleRetriever class instantiates and uses a
Timer, which implements the
IDisposable interface since it makes use of the Win32 API. It makes sense to dispose it when the singleton object is no longer referenced. The most straightforward way of doing this is by implementing the
IDisposable interface and -inside the
Dispose method - call the namesake method on the timer. This ensures that when the component is destroyed the timer has the chance to release its resources. This wouldn't happen if you didn't implement the
IDisposable interface and the container wasn't smart enough to understand that it should call the
The snippet below shows the changes needed to take advantage of the decommission lifecycle on the
Note that no additional configuration was required to apply the decommission lifecycle to the component. As for the
IStartable interface, the container was smart enough to infer the task it needed to accomplish.
Note: The above implementation of the disposable pattern is not recommended according to the .NET Framework Design Guidelines. It has been simplified to fit the needs of the sample application.
Lifestyles, startable components and lifecycles may be a bit confusing at first, as well as the usefulness of calling the
Release method on the container to release components. The general rule is that it's good to release as soon as you've finished using a component. You've seen that often the
Release method - in practice - doesn't perform any action. If a component has no decommission concerns, then the
Release method is a no-op, unless its lifestyle is pooled. In this case, its release pushes it back into the pool so it needs to be released once used, to avoid emptying the pool. Even if a component is transient the release won't perform any action, unless it has decommission concerns. In that case, the
Dispose method will be called because the component it's not referenced anymore. In the sample application all components were singletons, so both decommission and startable concerns occurred at container disposal instead of component release.
In general, to avoid mistakes and make sense of how this all works, my advice is to use the debugger to see when all those methods are called.
In this last article I've introduced the remaining and less intuitive features of Windsor Container, such as lifestyles, facilities and lifecycles. At the same time they represent the most flexible extension points of Windsor. I've shown you how to take advantage of them in the sample application I've developed step-by-step throughout the set of articles.
I hope I've been able to hand on my knowledge and pleasure of working with Windsor; and that you've enjoyed reading through the articles.
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...
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
A tiny bit of Dependency Injection and a C# delegate surprise
Party with Palermo @ DevTeach is tomorrow!!
Rendering individual controls for AJAX Callbacks
Silverlight 2 Beta 1 Controls Available, including Source and Unit Tests
ASP.Net MVC Framework - Create your own IControllerFactory and use Spring.Net
ASP.Net MVC Framework an early look
Custom Controls in ASP.NET (Part 1)
Accessing and Updating Data in ASP.NET 2.0: Creating Custom Parameter Controls
Please login to rate or to leave a comment.