Chi*_*esh 23 c# dependency-injection 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<IReport>().ImplementedBy<NortonService>());
container.Register(Component.For<ILogger>().ImplementedBy<FileLogger>());
IReport service = container.Resolve<IReport>();
service.LogReport();
Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)
我希望NortonService始终使用Filelogger和McAfeeService来使用数据库记录器.
在上面的程序中,我无法将NortonService绑定到FileLogger.
怎么做?
Chi*_*esh 27
上面的答案引导我进行内联依赖和功能服务覆盖
这是注册码:
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();
Run Code Online (Sandbox Code Playgroud)
输出:
McAfee Scan has Logged data to a database
Norton Scan has Logged data to a file
Run Code Online (Sandbox Code Playgroud)
我有一个非常类似的问题,一个接口的两个实现和另一个接口的两个实现.我想强制使用这些接口的特定实现.
我的班级结构看起来像这样 -

我查看了命名约定,但并不喜欢它.相反,我使用以下 -
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>())
);
Run Code Online (Sandbox Code Playgroud)
关于这种方法的完整信息在这里.在该帖子提供的源代码中,我展示了另外两种实现相同结果的方法.
小智 2
我的答案可能不是最好的,您可以使用命名方法来解决多重实现:
container.Register(Component.For(typeof(ILogger))
.ImplementedBy(typeof(FileLogger))
.Named("FileLoggerIoC")
.LifestylePerWebRequest() ,
Component.For(typeof(ILogger))
.ImplementedBy(typeof(DatabaseLogger))
.Named("DatabaseLoggerIoC")
.LifestylePerWebRequest());
Run Code Online (Sandbox Code Playgroud)
在您的调用函数中,您需要按名称解析它:-
var fileLog = container.Resolve("FileLoggerIoC", typeof(ILogger));
var DbLog = container.Resolve("DatabaseLoggerIoC", typeof(ILogger));
Run Code Online (Sandbox Code Playgroud)
我的方法可能不是最好的方法,因为人们不喜欢服务定位器来获取组件,您可以使用它作为临时解决方案。
| 归档时间: |
|
| 查看次数: |
16880 次 |
| 最近记录: |