The registration API is very nice, you can do a lot with it and I
prefer it over XML config or Binsor. But unfortunately the
documentation is not too good. For example, I don't get the advantage
of using Parameters() when there's also DependsOn(). So I decided to
do something about it, and started writing some documentation today.
But i was wondering if anyone else has started too? No point in people
doing double work.
Also, I'd like some feedback on the start i made so far. Like: the
writing style, is using tests useful or not etc. I've never written
any real documentation :) Here's what I have so far:
Castle Registration API for MicroKernel and Windsor IOC containers.
There are several ways to register and configure services and
components in the container:
- Using the various AddComponent... methods,
- Using the XML registration API,
- Using Bindsor,
- Using the registration API.
These can also be combined, depending on the needs of the application.
For example, ypu can register most of the services with the
registration API, but configure some components with XML so you don’t
have to rebuild with each change.
This document will describe how to use the registration API to
configure your container. The container can be a WindsorContainer or
just the MicroKernel, both support the registration API.
Registering a component
The starting point for registering anything in the container is the
container’s Register() method, with has one or more IRegistration
objects as parameter. The simplest way to create those objects is
using the static Castle.MicroKernel.Registration.Component class. Its
For() method returns a ComponentRegistration that you can use to
configure the component.
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using MbUnit.Framework;
[Test]
public void register_component()
{
container.Register(
Component.For<IClock>().ImplementedBy<NowClock>()
);
Assert.IsTrue(container.HasComponent(typeof(IClock)));
var resolved = container.Resolve<IClock>();
Assert.AreEqual(typeof(NowClock), resolved.GetType());
// You should normally always release the component when you have
resolved it yourself.
// To keep the tests simple, it will not be done in each tests.
container.ReleaseComponent(resolved);
}
/// <summary>
/// The service.
/// </summary>
public interface IClock
{
DateTime GetTime();
}
/// <summary>
/// A component, first implementation of the service.
/// </summary>
public class NowClock : IClock
{
public DateTime GetTime()
{
return DateTime.Now;
}
}
Specifying a name for the component
The default name for a registered component is its full type name. You
can specify a different name using the Named() method.
[Test]
public void register_component_with_explicit_name()
{
container.Register(
Component.For<IClock>().ImplementedBy<NowClock>().Named("clock")
);
Assert.IsTrue(container.HasComponent("clock"));
Assert.IsFalse(container.HasComponent(typeof(NowClock).FullName));
}
Configuring string parameters for components
Many components need to be configured. As an example, see the WebClock
below, which needs an url to get the time from the internet. This url
can be specified using the Parameters() method.
[Test]
public void register_component_with__string_parameter()
{
string timeUrl = "http://clock.com/currenttime";
container.Register(
Component.For<IClock>().ImplementedBy<WebClock>()
.Parameters(Parameter.ForKey("url").Eq(timeUrl))
);
var resolved = container.Resolve<IClock>() as WebClock;
Assert.AreEqual(timeUrl, resolved.Url);
}
/// <summary>
/// Supposedly retrieves the time from some website.
/// </summary>
public class WebClock : IClock
{
public WebClock(string url)
{
Url = url;
}
public DateTime GetTime()
{
return DateTime.MinValue;
}
public string Url
{
get;
private set;
}
}
Configuring parameters of other types
Many parameters are not strings, but some other type. But Parameters()
only accepts string values, which can lead to formatting woes
(DateTime for example) and other problems. For these situations you
can use the DependsOn() method. This method configures the component
using objects of any type you like. DependsOn() accepts PropertyKeys
(constructed using Property.ForKey()), a dictionary or an anonymous
object (that will be converted into a dictionary).
[Test]
public void register_component_with_parameter_using_DependsOn()
{
DateTime time1001 = new DateTime(1001, 2, 3);
// These registrations all configure the clock in the same way.
container.Register(
Component.For<IClock>().ImplementedBy<StaticClock>()
.Named("clock1")
.DependsOn(Property.ForKey("time").Eq(time1001)),
Component.For<IClock>().ImplementedBy<StaticClock>()
.Named("clock2")
.DependsOn(new { time = time1001 }),
Component.For<IClock>().ImplementedBy<StaticClock>()
.Named("clock3")
.DependsOn(new Hashtable { { "time", time1001 } })
);
var clocks = container.ResolveAll<IClock>();
Assert.AreEqual(3, clocks.Length);
foreach (IClock clock in clocks)
{
Assert.AreEqual(time1001, clock.GetTime());
}
}
/// <summary>
/// This component needs a parameter.
/// </summary>
public class StaticClock : IClock
{
private readonly DateTime time;
public StaticClock(DateTime time)
{
this.time = time;
}
public DateTime GetTime()
{
return time;
}
}
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Castle Project Development List" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/castle-project-devel?hl=en
-~----------~----~----~----~------~----~------~--~---