如何根据构造函数参数名称注入适当的依赖项

时间:2011-08-07 15:14:50

标签: c# dependency-injection castle-windsor

我有一些正在被少数具体类型使用的界面,例如EmailFormatterTextMessageFormatter等。

public interface IFormatter<T>
{
    T Format(CompletedItem completedItem);
}

我遇到的问题是我的EmailNotificationService是我想要注入EmailFormatter。此服务的构造函数签名为public EmailNotificationService(IFormatter<string> emailFormatter)

我很确定我之前已经看过这个,但是我如何在Windsor中注册它,以便在构造函数参数名称为EmailFormatter时注入emailFormatter

这是我的温莎注册码。

container.Register(Component.For<IFormatter<string>>().ImplementedBy<EmailFormatter>());

2 个答案:

答案 0 :(得分:9)

请勿尝试在DI配置中解决此问题。相反,在应用程序的设计中解决它。在我看来,你已经使用相同的界面定义了几个不同的东西。你的要求很明显,因为你说:

  

我想注入EmailFormatter

你不想注入格式化程序;你想注入一个电子邮件格式化程序。换句话说,您违反了Liskov Substitution Principle。在应用程序中修复此问题。定义IEmailFormatter界面,让EmailNotificationService依赖于此:

public interface IEmailFormatter
{
    string Format(CompletedItem completedItem);
}

public class EmailNotificationService
{
    public EmailNotificationService(IEmailFormatter formatter)
    {
    }
}

这有两个重要的优点:

  1. 它使代码更易于维护,因为现在很清楚什么样的依赖EmailNotificationService确实存在。
  2. 它使DI配置更容易,更易于维护。只要看看Zach答案的依赖注册,你就会理解我在说什么。

答案 1 :(得分:6)

服务代码:

public EmailNotificationService(IFormatter<string> emailFormatter){...}

依赖注册码:

container.Register(
    Component.For<IFormatter<string>().ImplementedBy<TextMessageFormatter>().Named("TextMessageFormatter"),
    Component.For<IFormatter<string>().ImplementedBy<EmailFormatter>().Named("EmailFormatter"),
    Component.For<INotificationService>().ImplementedBy<EmailNotificationService>().ServiceOverrrides(
        ServiceOverride.ForKey("emailFormatter").Eq("EmailFormatter"))
);