…continued from part 1.
Objectives
- Understand LifeStyle
- Understand LifeCycle
System requirements
- Microsoft Visual Studio 2008 SP1 (professional edition)
Prequisites
- Fundamental knowledge of software development in .NET 3.5
- Basic knowledge of Castle
Understand LifeStyle
LifeStyle is a strategy that is related to an instance of a component. The supported lifestyles are:
- Singleton: only one instance will be created for the whole life of the container. This is the default lifestyle.
- Transient: for each request a new instance if the component is created
- PerThread: for each thread there exists only one instance of a component
- Pooled: Instances will be pooled to avoid unnecessary constructions
- Custom: the instantiation of components is handled by your custom ILifestyleManager implementation
The default lifestyle is singleton. To indicate which lifestyle you want to use, you can use attributes to decorate the class:
[Transient]
public class CustomerRepository : ICustomerRepository
{
…
}
or in the configuration file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="castle"
type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,
Castle.Windsor" />
</configSections>
<castle>
<components>
<component
id="customer.business"
service="CastleExample.ICustomerBusiness, CastleExample"
lifestyle="transient"
type="CastleExample.CustomerBusiness, CastleExample" />
<component
id="customer.repository"
service="CastleExample.ICustomerRepository, CastleExample"
lifestyle="transient"
type="CastleExample.MockCustomerRepository, CastleExample" />
</components>
</castle>
</configuration>
I prefer to do it in configuration because otherwise the code will be coupled again to the Castle container, or, in complicated projects, it may be handier to do it in code but in that case, create specific classes that are responsible for these configuration tasks, so that in your code you have as little as dependencies to Castle as possible.
So try this: add a transient lifestyle to the components in the configuration file, and to see the effect, modify the constructor of CustomerBusiness and add constructors to CustomerRepository and MockCustomerRepository as follows:
public class CustomerBusiness : ICustomerBusiness { private ICustomerRepository customerRepository; public CustomerBusiness(ICustomerRepository customerRepository) { // using constructor injection the concrete customer repository is injected this.customerRepository = customerRepository; Console.WriteLine("CustomerBusiness constructor"); } … } public class CustomerRepository : ICustomerRepository { public CustomerRepository() { Console.WriteLine("MockCustomerRepository constructor"); } … } public class MockCustomerRepository : ICustomerRepository { public MockCustomerRepository() { Console.WriteLine("MockCustomerRepository constructor"); } … }
Modify Program.cs:
static void Main(string[] args)
{
…
// Use business
UseRegisteredBusiness();
UseRegisteredBusiness();
UseRegisteredBusiness();
}
If you run the application, you will notice that each constructor is only called once and so there is only one instance created of the components for all calls:
Change the configuration that components use the transient lifestyle, and then run the application again to see the difference:
Now for each call of the business component, the constructors are called, which means that new objects are created for each call.
Understand LifeCycle
On the other hand there is LifeCycle, which is a strategy that is related to the different phases of an instance. It means that we can implement a number of interfaces; and these implementations are executed at the right time. Out of the box there are two groups of lifecycles:
- Commission: these are executed when the component is being created. Interfaces are:
- Castle.Model.IInitializable
- System.ComponentModel.ISupportInitialize
- Decommission: these are executed when the component is being destructed. Interface is:
- System.IDisposable
So, bottom line: if you implement one of these interfaces for your component, Castle will take care of calling your implementations at the right time. Notice that if you use these, the coupling to Castle container will be higher.

