Search code examples
dependency-injectioninversion-of-controlcastle-windsor

Windsor Castle multiple components for a given service


I have an ILog interface and 2 possible implementations: a console log and a file log. I'm using Windsor Castle in an MVC application therefore i have the following code at controller installer:

container.Register(
            Component.For<ILogFactory>().ImplementedBy<LogFactory>().Named("first").OnCreate(x => x.initialize(LogType.Console, null)).LifestyleSingleton(),
            Component.For<ILogFactory>().ImplementedBy<LogFactory>().Named("second").OnCreate(x => x.initialize(LogType.File, null)).LifestyleSingleton(),
            Component.For<ILog>().UsingFactoryMethod(kernel => kernel.Resolve<ILogFactory>("first").GetLog(LogType.Console)).Named("first_log").LifestyleSingleton(),
            Component.For<ILog>().UsingFactoryMethod(kernel => kernel.Resolve<ILogFactory>("second").GetLog(LogType.File)).Named("second_log").LifestyleSingleton()
        );

In my TestController i have the following code:

private ILog log;

public TestController(ILog _log)
{
    log = _log;
}

I'm wondering HOW i could decide to inject the ILog named first_log or second_log


Solution

  • I found a solution for my scenario. The TestController needs the 2 ILogs defined:

    public class TestController : Controller 
    { 
    private ILog log1; 
    private ILog log2; 
    
    public TestController(ILog _log1, ILog _log2) 
    { 
    log1 = _log1; 
    log2 = _log2; 
    identifier = _identifier; 
    }
    

    Then it is necessary to add:

    container.Register(
    Component.For<MyController>().DependsOn(
     ServiceOverride.ForKey("_log1").Eq("first_log"),
     ServiceOverride.ForKey("_log2").Eq("second_log")).LifestyleTransient()
     );
    

    replacing the actual default content:

    container.Register(
     Classes.
     FromThisAssembly().
     BasedOn<IController>().
     If(c => c.Name.EndsWith("Controller")).
     LifestyleTransient());