[英]Castle Windsor - multiple implementation of an interface
在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();
}
}
我希望NortonService始終使用Filelogger,而McAfeeService使用Database Logger。
在上面的程序中,我無法將NortonService綁定到FileLogger。
怎么做?
上面的答案將我引向了內聯依賴項和要素服務覆蓋
這是注冊碼:
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();
輸出:
McAfee Scan has Logged data to a database
Norton Scan has Logged data to a file
我有一個非常像這樣的問題,一個接口的兩個實現和另一個接口的兩個實現。 我想強制使用這些接口的特定實現。
我的班級結構看起來像這樣-
我看了命名約定,但並不十分喜歡。 相反,我使用以下內容-
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>())
);
有關此方法的完整信息在這里 。 在該帖子提供的源代碼中,我展示了實現相同結果的其他兩種方法。
如果要在運行時執行此操作,可以通過IHandlerSelector實現。 編寫一個實現IHandlerSelector的類。 它提供了SelectHandler方法,使您可以定義在運行時有條件綁定的條件。 在這種情況下,處理程序是Windsor中參與實例構造的組件。 有關更多詳細信息,請參見此處 。
我的答案可能不是最好的答案,您可以使用命名方法來解決多種實現:
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));
我的方法可能不是最好的方法,因為人們不喜歡使用服務定位器來獲取組件,您可以將其用作臨時解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.