2011-08-07 27 views
6

我有这个接口,正在使用的具体类型屈指可数,如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>()); 

回答

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")) 
); 
+0

感谢您的回答。我正在寻找错误的东西。 :D – User

+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答案的依赖注册,你就会明白我在说什么。
+0

我理解你的意思,但是通过单独的界面来完成一件事情,格式化内容并不是多余的? – User

+2

@User:让'EmailNotificationService'依赖于'IFormatter '意味着任何字符串格式化程序都可以正常工作,而只能使用可以输出邮件的格式化程序正常工作。所以'EmailNotificationService'关注的是不一样的。虽然“IMailFormatter”和“IFormatter”具有相同的输入和输出类型,但“IMailFormatter”的合约更加强大,因为它明确指出了返回的字符串类型,而“IFormatter ”可能返回任何内容。 – Steven

相关问题