Castle Windsor – 多个接口实现
在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().ImplementedBy()); container.Register(Component.For().ImplementedBy()); IReport service = container.Resolve(); service.LogReport(); Console.ReadLine(); } }
我希望NortonService始终使用Filelogger和McAfeeService来使用数据库记录器。
在上面的程序中,我无法将NortonService绑定到FileLogger。
怎么做?
上面的答案引导我进行内联依赖和function服务覆盖
这是注册码:
container.Register(Component.For().ImplementedBy().Named("nortonService")); container.Register(Component.For().ImplementedBy()); container.Register(Component.For().ImplementedBy()); container.Register( Component.For().ImplementedBy().Named("mcafeeService") .DependsOn(Dependency.OnComponent()) ); IReport mcafeescan = container.Resolve("mcafeeService"); mcafeescan.LogReport(); IReport nortonscan = container.Resolve ("nortonService"); nortonscan.LogReport();
输出:
McAfee Scan has Logged data to a database Norton Scan has Logged data to a file
我有一个非常类似的问题,一个接口的两个实现和另一个接口的两个实现。 我想强制使用这些接口的特定实现。
我的class级结构看起来像这样 –
我查看了命名约定,但并不喜欢它。 相反,我使用以下 –
public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register( Component.For().ImplementedBy() ,Component.For().ImplementedBy() ,Component.For().ImplementedBy() .DependsOn(Dependency.OnComponent()) ,Component.For().ImplementedBy() .DependsOn(Dependency.OnComponent()) ,Component.For().LifestyleTransient() .DependsOn(Dependency.OnComponent()) );
关于这种方法的完整信息在这里 。 在该post提供的源代码中,我展示了另外两种实现相同结果的方法。
我的答案可能不是最好的,您可以使用命名方法来解决多个实现:
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));
我的方法可能不是最好的,因为人们不喜欢服务定位器来获取组件,你可以使用它作为临时解决方案。
如果你想在运行时这样做,可以通过IHandlerSelector实现。 编写一个实现IHandlerSelector的类。 它提供了一个方法SelectHandler,它允许您在运行时有条件地定义绑定条件。 在这种情况下,处理程序是Windsor中参与实例构造的组件。 请参阅此处了解更多详情。