简体   繁体   中英

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

Sorry for the late response.

You could use a subdependency resolver. It allows you resolve a specific component for a dependency of another componennt. the code belows should (not tested) resolve the ILog based on the name of the parameter in the constructor of the TestController. So TestController (ILog first) will resolve the ILog named first.

class SubDepResolver : ISubDependencyResolver
{
  private IKernel kernel;
  SubDepResolver(IKernel kernel)
  {
    this.kernel = kernel;
  }

  public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model,
    DependencyModel dependency)
  {
    if (model.GetComponentType() != typeof(TestController)) return false;
    if (dependency.GetComponentType() != typeof(ILog)) return false;
    return true;
  }

  public object Resolve(
    CreationContext context, 
    ISubDependencyResolver contextHandlerResolver, 
    ComponentModel model,
    DependencyModel dependency)
  {
    var handlers = kernel.GetHandlers(typeof(ILog));
    var handler = handlers.Single(h => h.GetComponentName() == dependency.DependencyKey);
    return handler.Resolve(context);
  }
}

Add the resolver using :

container.Kernel.Resolver.AddSubResolver(new SubDepResolver(container.Kernel));

Good luck, Marwijn.

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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM