Castle Windsor - multiple implementation of an interface

前端 未结 4 1539
小鲜肉
小鲜肉 2020-12-09 16:02

While registering components in Castle Windsor, how do we bind specific implementation of an interface to a component that has a dependency on that interface. I know in adva

相关标签:
4条回答
  • 2020-12-09 16:28

    I had a problem very like this, two implementation of one interface and two implementation of another interface. I wanted to force usage of particular implementations of those interfaces.

    My class structure looked like this -

    enter image description here

    I looked at the naming convention, but didn't really like it. Instead I used the following -

        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
        container.Register(
             Component.For<IMessageLoader>().ImplementedBy<MessageLoaderDatabase>()
            ,Component.For<IMessageLoader>().ImplementedBy<MessageLoaderFile>()
    
            ,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceDatabase>()
                .DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderDatabase>())
    
            ,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceFile>()
                .DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderFile>())
    
            ,Component.For<MessageOfTheDayController>().LifestyleTransient()
                .DependsOn(Dependency.OnComponent<IMessageOfTheDayService, MessageOfTheDayServiceFile>())
        );
    

    Full info about this approach is here. In the source code provided with that post I show two other ways of achieving the same result.

    0 讨论(0)
  • 2020-12-09 16:30

    The above answers lead me to inline dependencies and the feature service override

    Here is the registration code:

    container.Register(Component.For<IReport>().ImplementedBy<NortonService>().Named("nortonService"));
    
    container.Register(Component.For<ILogger>().ImplementedBy<FileLogger>());
    container.Register(Component.For<ILogger>().ImplementedBy<DatabaseLogger>());
    
    container.Register(
        Component.For<IReport>().ImplementedBy<McAfeeService>().Named("mcafeeService")
            .DependsOn(Dependency.OnComponent<ILogger, DatabaseLogger>())
    );
    
    IReport mcafeescan = container.Resolve<IReport>("mcafeeService");
    mcafeescan.LogReport();
    
    IReport nortonscan = container.Resolve<IReport>("nortonService");
    nortonscan.LogReport();
    

    Output:

    McAfee Scan has Logged data to a database
    Norton Scan has Logged data to a file
    
    0 讨论(0)
  • 2020-12-09 16:33

    If you want to do it at runtime, This can be acheived through IHandlerSelector. Write a class that implements IHandlerSelector. It provides a method SelectHandler which will let you define the condition for binding conditionally at runtime. A Handler in this case is a component in Windsor that participates in instance construction. Refer here for more details.

    0 讨论(0)
  • 2020-12-09 16:38

    My answer maybe not the best one, you can use naming method to resolve multi implementation:

     container.Register(Component.For(typeof(ILogger))
              .ImplementedBy(typeof(FileLogger))
              .Named("FileLoggerIoC")
              .LifestylePerWebRequest() ,
              Component.For(typeof(ILogger))
              .ImplementedBy(typeof(DatabaseLogger))
              .Named("DatabaseLoggerIoC")
              .LifestylePerWebRequest());
    

    In your calling functions, you need to resolve it by name :-

    var fileLog = container.Resolve("FileLoggerIoC", typeof(ILogger));
    var DbLog = container.Resolve("DatabaseLoggerIoC", typeof(ILogger));
    

    Mine method maybe not the best one as people don't like service locator to get the components, you can use this as temporary solution.

    0 讨论(0)
提交回复
热议问题