簡體   English   中英

溫莎城堡-接口的多種實現

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM