Search code examples
c#dependency-injectioncastle-windsor

Castle Windsor Inline dependencies


I need to use Inline Dependencies feature of castle-windsor. I need to inject specific component in chain of dependencies. I have a situation like this.

static void Main(string[] args)
{
    var container = new Castle.Windsor.WindsorContainer();

    container.Register(
        Component.For<IHigherBusiness>()
                 .ImplementedBy<HigherBusiness>()
                 .DependsOn(Dependency.OnComponent<ILogger, FullDetailLogger>())
        );

    container.Register(Component.For<ISomeBusiness>()
                 .ImplementedBy<Business>());
    container.Register(Component.For<ILogger>()                         
                 .ImplementedBy<FullDetailLogger>().IsFallback());
    container.Register(Component.For<ILogger>()
                 .ImplementedBy<SimpleLogger>());

    var business = container.Resolve<IHigherBusiness>();
    business.DoSomething();

    var logger = container.Resolve<ILogger>();
    logger.Log("Some Log... ."); 
}

with business ...

public interface IHigherBusiness
{
    void DoSomething();
}

public class HigherBusiness : IHigherBusiness
{
    private ISomeBusiness someBusiness;

    public HigherBusiness(ISomeBusiness someBusiness)
    {
        this.someBusiness = someBusiness;
    }
    public void DoSomething()
    {
        someBusiness.DoSomething();
    }
}

public interface ISomeBusiness
{
    void DoSomething();
}

public class Business : ISomeBusiness
{
    private ILogger logger;
    public Business(ILogger logger)
    {
        this.logger = logger;
    }
    public void DoSomething()
    {
        logger.Log("Message");
    }
}

and loggers ...

public interface ILogger
{
    void Log(string message);
}

public class SimpleLogger : ILogger
{

    public void Log(string message)
    {
        Console.WriteLine("Simple Logger: " + message);
    }
}

public class FullDetailLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine("Full detail Logger: " + message);
    }
}

The result is:

Simple Logger: Message
Simple Logger: Some Log... .

but I expect this:

Full detail Logger: Message
Simple Logger: Some Log... .

How can I achieve this ?


Solution

  • DependsOn works only one level down so You have to make Business depend on specific ILogger.

    You can do a trick like this:

        static void Main(string[] args)
        {
    
            var container = new Castle.Windsor.WindsorContainer();
    
            container.Register(
                    Component.For<IHigherBusiness>()
                    .ImplementedBy<HigherBusiness>()
                    .DependsOn(Dependency.OnComponent(typeof(ISomeBusiness),
                                "BusinessWithExtendedLogger"))
                );
            container.Register(Component.For<ISomeBusiness>().ImplementedBy<Business>()
                    .DependsOn(Dependency.OnComponent<ILogger, FullDetailLogger>())
                    .Named("BusinessWithExtendedLogger")
                );
            container.Register(Component.For<ISomeBusiness>().ImplementedBy<Business>()
                    .DependsOn(Dependency.OnComponent<ILogger, SimpleLogger>())
                    .IsDefault()
                );
            container.Register(Component.For<ILogger>().ImplementedBy<FullDetailLogger>()
                    .IsFallback()
                );
            container.Register(Component.For<ILogger>().ImplementedBy<SimpleLogger>());
    
            var business = container.Resolve<IHigherBusiness>();
            business.DoSomething();
    
            var normalBusiness = container.Resolve<ISomeBusiness>();
            normalBusiness.DoSomething();
    
            var logger = container.Resolve<ILogger>();
            logger.Log("Some Log... .");
            Console.ReadKey();
    
        }
    

    This returns:

    Full detail Logger: Message

    Simple Logger: Message

    Simple Logger: Some Log... .

    Giving You FullDetailLogger only for IHigherBussiness