When I follow good software development practices like
I find myself writing plenty of factory classes.
These factory classes often fall in one of the two categories:
I need to create instance of generic service for specific type e.g. I want to get
service that implements ICommandHandler<TCommand> for TCommand type
I must pass parameters and/or configuration to the service before I
can use it e.g. HeuristicSearch service has quality constructor parameter
to decide what solutions are good enough for the user
In cases like these we can use typed factory feature to generate
Things to remember when using typed factory:
Release method in factory interface is optional.
It is a good practice to
always include Release method in factory interface and to release all instances
created using factory when they are no longer needed
In case of transient or per-web-request components that are disposable
not releasing component will result in a memory leak
Remember that some factories should be implemented manually especially these
that contain domain knowledge e.g. factory that selects discount
strategy based on user profile
Sometime we want to get all components that provide given service.
For example we may try to implement message filtering component and
we want to get all components that implement IFilter interface.
We may achieve this easily by using Castle Windsor CollectionResolver:
Since registering CollectionResolver requires a bit of interaction
with a container it is advisable to wrap that logic into custom facility:
Castle Windsor is very flexible when it comes to registering components
by convention, we may scan selected assemblies and/or namespaces, we
may even select components to register by testing component Type.
PITFALL: Avoid creating conventions based on type name (e.g. register all classes that
have names ending with Repository) as
much as possible. It is always better to create empty marker interface
e.g. IApplicationService and use it to register all necessary components.
Castle Windsor installers allow us to group component registrations into
reusable pieces of code. The real power of installers comes from the fact that
we may pass them arguments or in other words we may configure them.
For example installer may take a single argument that tells what lifestyle should
be applied to all registrations contained in the installer. Such installer can
be used in both ASP.NET MVC app when most of the components will be
registered as PerWebRequest and in Windows service app where components will
be registered as either Transient or Singleton.
Here is example of very simple installer:
Fallback and default components
When we start grouping registrations into installers often we will find ourselves
in situation that we want to register given service only when user of the installer
didn’t provide she’s own implementation. We may achieve this by passing parameters
to the installer but a fallback components are a better choice here.
Components registered as fallbacks will be used by the container only when there is no
other component that provides given service:
Since word isn’t perfect it happens from time to time that we want to
overwrite component registration for some particular service. This usually happens
because author of the installer doesn’t use fallback components. But don’t panic
Castle Windsor allow us to overwrite service registrations using default components:
Interceptors are most powerful Castle Windsor feature that
brings power of aspect oriented programming
Interceptors can be used to implement transaction management, logging, security checks,
we may use them to gather performance related statistics and for many other purposes.
Here is a simple interceptor that log the invocations of all component methods:
When you start writing your own interceptors it is generally advisable to
create custom attribute e.g. TransactionalAttribute to mark classes that
should have interceptors attached.
Then you should write your own facility that will scan all components
registered in container
and will attach interceptor for these marked with your custom attribute.
Here is a good example of this approach
used to implement caching.