Home

Castle Stronghold

Using Type converters

When supplying configuration dependencies to components, the MicroKernel uses the Conversion SubSystem. Its role is to manage type conversions. The MicroKernel then reflect the type expected by the component and pass the configuration value.

The Conversion SubSystem is nothing more than a sequence of TypeConverter. Whenever a conversion must be performed, the Conversion SubSystem interrogates each TypeConverter, until it finds one that is able to convert to he type requested.

The table below lists the types which conversion is supported by default.

TypeNested configuration nodeExample
System.Int32, Int16, Int64-10
System.UInt32, UInt16, UInt64-10
System.Char-a
System.Single, Double, Decimal-13.22
System.String-mail.host.com
System.Byte, SByte-144
System.Boolean-0
System.DateTime-11022005
System.Type-Components.MyComponent, Components
System.ArrayarraySee next document
System.Collections.IListlistSee next document
System.Collections.IDictionarydictionarySee next document

Creation your own TypeConverter

It is fairly easy to create your own converter to handle simple of complex values. For example, suppose one of your components uses an object to configure itself:


public class ServerConfig
{
    private int port;
    private string host;
    private bool accept;
    
    public int Port
    {
        get { return port; }
        set { port = value; }
    }
    
    public string Host
    {
        get { return host; }
        set { host = value; }
    }
    
    public bool Accept
    {
        get { return accept; }
        set { accept = value; }
    }
}    

public class ComplexIMServer
{
    public ComplexIMServer(ServerConfig config)
    {
        ...
    }
}
    

And you would like to configure the ComplexIMServer service with the following configuration:

    
<component id="complex.server">
    
    <parameters>
        <config>
            <serverconfig>
                <port>120</port>
                <host>server1.com</host>
                <accept>false</accept>
            </serverconfig>
        </config>
    </parameters>

</component>
Quick Note

Note that in the snippet above, config is the construct parameter name. serverconfig will be the configuration node passed to our TypeConverter.

The following is a possible implementation of the type converter.


using Castle.Core.Configuration;


public class ServerConfigConverter : AbstractTypeConverter
{
    public ServerConfigConverter()
    {
    }

    public override bool CanHandleType(Type type)
    {
        return type == typeof(ServerConfig);
    }

    public override object PerformConversion(String value, Type targetType)
    {
        throw new NotImplementedException();
    }

    public override object PerformConversion(IConfiguration configuration, Type targetType)
    {
        ServerConfig config = new ServerConfig();
    
        foreach(IConfiguration childConfig in configuration.Children)
        {
            if (childConfig.Name == "host")
            {
                config.Host = (String) 
                    Context.Composition.PerformConversion(childConfig, typeof(String));
            }
            else if (childConfig.Name == "port")
            {
                config.Port = (int) 
                    Context.Composition.PerformConversion(childConfig, typeof(int));
            }
            else if (childConfig.Name == "accept")
            {
                config.Accept = (bool) 
                    Context.Composition.PerformConversion(childConfig, typeof(bool));
            }
        }

        return config;
    }
}

From the implementation above you can see that we rely on the Conversion SubSystem to convert strings, int and bools.

The last step is registering the TypeConverter on the SubSystem. If you use Windsor Container and allow it to register the components for you, then this is a trick part: you must register the TypeConverter before the container tries to register the components. This is important. The most simple way to do this is to create your own container class that extends WindsorContainer. For example:


public class MyContainer : WindsorContainer
{
    public MyContainer(IConfigurationInterpreter interpreter)
    {
        // Registers the type converter:
        
        IConversionManager manager = (IConversionManager)
            Kernel.GetSubSystem(Castle.MicroKernel.SubSystemConstants.ConversionManagerKey);
        
        manager.Add(new ServerConfigConverter());
        
        // Process the configuration
        
        interpreter.ProcessResource(interpreter.Source, Kernel.ConfigurationStore);
        
        // Install the components
        
        Installer.SetUp(this, Kernel.ConfigurationStore);
    }
}

The code above can then be used like the following:


IWindsorContainer container = new MyContainer(new XmlInterpreter());

ComplexIMServer server = (ComplexIMServer) container[typeof(ComplexIMServer)];
    
Google
Search WWW Search castleproject.org