C# Castle Windsor-接口的多个实现

C# Castle Windsor-接口的多个实现,c#,dependency-injection,castle-windsor,C#,Dependency Injection,Castle Windsor,在Castle Windsor中注册组件时,我们如何将接口的特定实现绑定到依赖于该接口的组件。我提前知道组件需要使用哪个实现 例如,我根据几个博客和教程中的代码创建了一个示例控制台应用程序 下面是代码 public interface IReport { void LogReport(); } public interface ILogger { string Log(); } public class FileLogger : ILogger { public st

在Castle Windsor中注册组件时,我们如何将接口的特定实现绑定到依赖于该接口的组件。我提前知道组件需要使用哪个实现

例如,我根据几个博客和教程中的代码创建了一个示例控制台应用程序

下面是代码

public interface IReport
{
    void LogReport();
}

public interface ILogger
{
    string Log();
}

public class FileLogger : ILogger
{
    public string Log()
    {
        return "Logged data to a file";
    }
}

public class DatabaseLogger : ILogger
{
    public string Log()
    {
        return "Logged data to a database";
    }
}

public class McAfeeService : IReport
{
    private readonly ILogger _logger;

    public McAfeeService(ILogger logger)
    {
        this._logger = logger;
    }

    public void LogReport()
    {
        string getLogResult = this._logger.Log();

        Console.WriteLine("McAfee Scan has " + getLogResult);
    }        
}

public class NortonService : IReport
{
    private readonly ILogger _logger;

    public NortonService(ILogger logger)
    {
        this._logger = logger;
    }

    public void LogReport()
    {
        string getLogResult = this._logger.Log();

        Console.WriteLine("Norton Scan has " + getLogResult);
    }
}

class Program
{
    private static IWindsorContainer container;

    static void Main(string[] args)
    {
        // Register components
        container = new WindsorContainer();

        container.Register(Component.For<IReport>().ImplementedBy<NortonService>());
        container.Register(Component.For<ILogger>().ImplementedBy<FileLogger>());

        IReport service = container.Resolve<IReport>();
        service.LogReport();

        Console.ReadLine();
    }
}
公共接口IReport
{
作废日志报告();
}
公共接口ILogger
{
字符串Log();
}
公共类文件记录器:ILogger
{
公共字符串日志()
{
返回“记录的数据到文件”;
}
}
公共类数据库记录器:ILogger
{
公共字符串日志()
{
返回“记录的数据到数据库”;
}
}
公共类服务:IReport
{
专用只读ILogger\u记录器;
公共McAfeeService(ILogger记录器)
{
这个。_logger=记录器;
}
公众假期日志报告()
{
字符串getLogResult=this.\u logger.Log();
Console.WriteLine(“McAfee扫描有”+getLogResult);
}        
}
公共类诺顿服务:IReport
{
专用只读ILogger\u记录器;
公共NortonService(ILogger记录器)
{
这个。_logger=记录器;
}
公众假期日志报告()
{
字符串getLogResult=this.\u logger.Log();
Console.WriteLine(“诺顿扫描有”+getLogResult);
}
}
班级计划
{
私有静态IWindsorContainer;
静态void Main(字符串[]参数)
{
//寄存器组件
容器=新WindsorContainer();
container.Register(Component.For().ImplementedBy());
container.Register(Component.For().ImplementedBy());
IReport服务=container.Resolve();
service.LogReport();
Console.ReadLine();
}
}
我希望NortonService始终使用文件记录器,McAfeeService始终使用数据库记录器

在上面的程序中,我无法将NortonService绑定到文件记录器


怎么做?

我的答案可能不是最好的,您可以使用命名方法来解决多重实现:

 container.Register(Component.For(typeof(ILogger))
          .ImplementedBy(typeof(FileLogger))
          .Named("FileLoggerIoC")
          .LifestylePerWebRequest() ,
          Component.For(typeof(ILogger))
          .ImplementedBy(typeof(DatabaseLogger))
          .Named("DatabaseLoggerIoC")
          .LifestylePerWebRequest());
在调用函数中,需要按名称解析:-

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

我的方法可能不是最好的方法,因为人们不喜欢使用service locator来获取组件,您可以将其用作临时解决方案。

以上答案将我引向内联依赖项和功能

这是注册码:

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

我遇到了一个非常类似的问题,一个接口的两个实现和另一个接口的两个实现。我想强制使用这些接口的特定实现

我的班级结构是这样的-

我看了一下命名惯例,但不太喜欢。相反,我使用了以下内容:

    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>())
    );
public void安装(IWindsorContainer,IConfigurationStore)
{
集装箱。登记(
Component.For().ImplementedBy()实现
,Component.For()。由()实现
,Component.For()。由()实现
.DependsOn(Dependency.OnComponent())
,Component.For()。由()实现
.DependsOn(Dependency.OnComponent())
,Component.For().LifestyleTransient()
.DependsOn(Dependency.OnComponent())
);

有关此方法的完整信息如下。在该帖子提供的源代码中,我展示了实现相同结果的其他两种方法。

如果您想在运行时执行此操作,可以通过IHandlerSelector实现。编写一个实现IHandlerSelector的类。它提供了一个方法SelectHandler,可以让您定义bin的条件在运行时有条件地刷新。在本例中,处理程序是Windsor中参与实例构造的组件。有关更多详细信息,请参阅