Home

Castle Stronghold

Table of contents

  • 1 Externalizing the container configuration
  • 2 Passing configuration parameters
  • 3 Choosing the notifier
  • 4 Passing a list of notifiers to HttpServiceWatcher

Using the configuration file

What we have developed so far might have sparked a few questions:

Those are good questions. By default the container will supply the first service registered. So the HttpServiceWatcher is getting an EmailFailureNotifier instance. We can change that using a service override.

You can pass a list of notifiers too, but you need to inform the container about what instances do you want to pass. Suppose you had ten implementations of IFailureNotifier. You must tell which ones should be passed. More on that shortly.

Finally, yes, you can supply an URL to HttpServiceWatcher and why not a list of emails to EmailFailureNotifier? We will see how to make all those things.

Externalizing the container configuration

So far we have used code to configure our container. Let's make this configuration external to the code, so we have more flexibility and we can make changes without recompiling the application.

The configuration is very minimum and, by default, is done in Xml. We can have a standalone xml file or use the configuration associated with the AppDomain. Let's use the latter.

Add an App.config file to your Visual Studio project:

    
<?xml version="1.0" encoding="utf-8" ?>
<configuration>

</configuration>

Visual Studio will take care of copying and renaming the file to your executable assembly name, for example: GettingStartedPart1.exe.config

Now add a section to configure Windsor Container:

    
<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <configSections>
        <section 
            name="castle"
            type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
    </configSections>

    <castle>

        <components>

        </components>

    </castle>
    
</configuration>

We can now move the configuration from the App.cs to the configuration, on the "castle" section. It will look like the following:

    
<castle>

    <components>
        
        <component 
            id="httpservicewatcher"
            type="GettingStartedPart1.HttpServiceWatcher, GettingStartedPart1" />

        <component 
            id="email.notifier"
            service="GettingStartedPart1.IFailureNotifier, GettingStartedPart1"
            type="GettingStartedPart1.EmailFailureNotifier, GettingStartedPart1" />

        <component 
            id="alarm.notifier"
            service="GettingStartedPart1.IFailureNotifier, GettingStartedPart1"
            type="GettingStartedPart1.AlarmFailureNotifier, GettingStartedPart1" />

        <component 
            id="form.component"
            type="GettingStartedPart1.Form1, GettingStartedPart1" />

    </components>

</castle>

Finally, we need to create the Windsor Container passing a configuration interpreter and a resource:


using Castle.Core.Resource;
using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;

public class App
{
    public static void Main()
    {
        IWindsorContainer container = 
            new WindsorContainer(
                new XmlInterpreter(new ConfigResource("castle")));
        
        // Request the component to use it
        Form1 form = (Form1) container[typeof(Form1)];
        
        // Use the component
        Application.Run(form);
        
        // Release it
        container.Release(form);
    }
}

Test your work and everything should work as expected.

Passing configuration parameters

Let's improve our HttpServiceWatcher to receive an URL that it should use to make request on. First, is this URL a necessary or optional parameter? Let's assume it is optional, so we should use a property:


public class HttpServiceWatcher
{
    private IFailureNotifier notifier;
    private string url = "default url";
    
    public HttpServiceWatcher(IFailureNotifier notifier)
    {
        this.notifier = notifier;
    }

    public string Url
    {
        get { return url; }
        set { url = value; }
    }

    ...

How to configure this parameter with the configuration? Simple: use the parameters node:

    
<component 
    id="httpservicewatcher"
    type="GettingStartedPart1.HttpServiceWatcher, GettingStartedPart1">
    
    <parameters>
        <Url>different url</Url>
    </parameters>
    
</component>

Each node enclosed by the parameters node should be named after a property or a constructor argument.

Choosing the notifier

As stated before, there are two notifiers and the HttpServiceWatcher is requesting one. Which one will it get? By default, the first one registered, which is the EmailFailureNotifier. But suppose you want to change that, how would you do it?

We need to make a service override. What does that mean? A service override a configuration entry that changes the MicroKernel behavior when resolving dependency. In the end, we need to change the configuration passing a different service to the constructor argument.


public HttpServiceWatcher(IFailureNotifier notifier)
{
    this.notifier = notifier;
}
    
<component 
    id="httpservicewatcher"
    type="GettingStartedPart1.HttpServiceWatcher, GettingStartedPart1">
    
    <parameters>
        <notifier>${alarm.notifier}</notifier>
        <Url>different url</Url>
    </parameters>
    
</component>

The ${} notation is called service lookup.

Passing a list of notifiers to HttpServiceWatcher

Suppose that you are not satisfied with the fact that the HttpServiceWatcher is receiving just one notifier instance. Well, let's make it receive an array of notifiers:


public class HttpServiceWatcher
{
    private IFailureNotifier[] notifiers;
    private string url = "default url";
    
    public HttpServiceWatcher(IFailureNotifier[] notifiers)
    {
        this.notifiers = notifiers;
    }

    ...
    

On our configuration, we need to make a few changes:

    
<component 
    id="httpservicewatcher"
    type="GettingStartedPart1.HttpServiceWatcher, GettingStartedPart1">
    
    <parameters>
        <notifiers>
            <array>
                <item>${email.notifier}</item>
                <item>${alarm.notifier}</item>
            </array>
        </notifiers>
        <Url>different url</Url>
    </parameters>
    
</component>

Proceed with Getting More.

Google
Search WWW Search castleproject.org