2
votes

I am new to Castle Windsor, so forgive me if I simply missed an obvious functionality here...

I am currently trying to switch a working project from pure DI to Castle. I have several components, which have a property dependency of type ILogger. My LoggerImpl is created via a static factory method like this:

LoggerImpl.GetLogger("LoggerName");

Each component which has an ILogger dependency currently (pure DI) receives a named logger when constructing the object tree, e.g.:

var component1 = new MyComponent1(dependencies...);
component.Logger = LoggerImpl.GetLogger("Component1Logger");
var component2 = new MyComponent2(dependencies...);
component.Logger = LoggerImpl.GetLogger("Component2Logger");

After switching to Castle Windsor, I registered a named ILogger singleton for each component that references it, and then assigned those loggers to my components using DependsOn(...). The code is more or less like this:

// register logger implementations
container.Register(Component.For<ILogger>()
    .ImplementedBy<RolexLogger>()
    .Named("Component1Logger")
    .UsingFactoryMethod(() => LoggerImpl.GetLogger("Component1Logger"));
container.Register(Component.For<ILogger>()
    .ImplementedBy<RolexLogger>()
    .Named("Component2Logger")
    .UsingFactoryMethod(() => LoggerImpl.GetLogger("Component2Logger"));

// register component implementations
container.Register(Component.For<IComponent1>()
    .ImplementedBy<MyComponent1>()
    .DependsOn(Dependency.OnComponent(typeof(ILogger), "Component1Logger")));
container.Register(Component.For<IComponent2>()
    .ImplementedBy<MyComponent2>()
    .DependsOn(Dependency.OnComponent(typeof(ILogger), "Component2Logger")));

This all seems to work, but I was wondering whether there's an easier way to do this? This seems like an awful lot of code, that will grow and grow as more components need their loggers.

I was wondering whether it's possible to register a single ILogger's implementation by LoggerImpl with Transient lifestyle, and then somehow control how instances of LoggerImpl get created each time a dependency to ILogger gets resolved?

I assume I could also use Dependency.OnValue(LoggerImpl.GetLogger("LoggerName")) when registering components, but then the LoggerImpl instances would not get registered in the container, and I have no idea whether that's OK or not.

Any comments, ideas and suggestions would be greatly appreciated.

1

1 Answers

2
votes

You can use subresolver

public class LoggerResolver : ISubDependencyResolver
{
    public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
    {
        return dependency.TargetType == typeof(ILogger);
    }

    public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
    {
        return LoggerImpl.GetLogger(model.Implementation.FullName);
    }
}

than add it into the kernel before any of your registrations

container.Kernel.Resolver.AddSubResolver(new LoggerResolver())