views:

165

answers:

3

I am working in a project that has two main parts: a class library assembly and the main application. Both are using Castle Windsor for IoC and both manually setup their list of of components in code (to aid refactoring and prevent the need for a config file). Currently the main application has code like this:

public static void Main()
{        
    // Perform library IoC setup
    LibraryComponent.Init();

    // Perform application IoC setup
    IoC.Register<IXyz, Abc>("abc");
    // etc, etc, ...

    // Start the application code ...
}

However the call to initialise the library doesn't seem like a good solution. What is the best way to setup a class library that uses an IoC container to decouple its internal components?



Edit:

  • Lusid proposed using a static method on each public component in the library that would in turn make the call to initialise. One possible way to make this a bit nicer would be to use something like PostSharp to do this in an aspect-oriented way. However I was hoping for something a bit more elegant ;-)

  • Lusid also proposed using the AppDomain.AssemblyLoad event to perform custom steps at load time, however I am really after a way to avoid the client assembly from requiring any setup code.


Thanks!

+1  A: 

I'm not sure if I'm understanding exactly the problem you are trying to solve, but my first guess is that you are looking for a way to decouple the need to call the Init method from your main application.

One method I've used in the past is a static constructor on a static class in the class library:

static public class LibraryComponent {
  static LibraryComponent() {
    Init();
  }
}

If you have multiple class libraries, and would like a quick and dirty way of evaluating all of them as they are loaded, here's a (kinda hairy) way:

[STAThread]
static void Main()
{
    AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(CurrentDomain_AssemblyLoad);
}

static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
    IEnumerable<Type> types = args.LoadedAssembly.GetTypes()
        .Where(t => typeof(IMyModuleInterface).IsAssignableFrom(t));
    foreach (Type t in types)
    {
        doSomethingWithType(t);
    }
}

The Where clause could be anything you want, of course. The code above would find any class deriving from IMyModuleInterface in each assembly that gets loaded into the current AppDomain, and then I can do something with it, whether it be registering dependencies, maintaining an internal list, whatever.

Might not be exactly what you are looking for, but hopefully it helps in some way.

Lusid
That is the problem I'm trying to solve. Although I wanted to avoid using static methods since they would have to go on every library component.
Luke Quinane
Hmmm... so, just to clarify, you have one class library or multiple class libraries? Because I would think that you could initialize everything you need inside of a single class library with a single static constructor?
Lusid
A: 

You could have a registration module. Basically LibraryComponent.Init() function takes an IRegistrar to wire everything up.

The IRegistrar could basically have a function Register(Type interface, Type implementation). The implimentor would map that function back to their IOC container.

The downside is that you can't rely on anything specific to the container your using.

flukus
A: 

Castle Windsor actually has a concept called facilities that are basically just ways of wrapping standardised pieces of configuration. In this model, you would simply add the two facilities to the container and they would do the work.

Of course, this wouldn't really be better than calling a library routine to do the work unless you configured the facilities in a configuration file (consider binsor). If you are really allergic to configuration files, your current solution is probably the best.

Julian Birch