使用IWindsorInstaller进行动态构造函数注入

时间:2012-05-23 14:37:34

标签: dependency-injection castle-windsor castle

我不确定这是否可行,但我仍然会问这个问题。

我有一个场景,我有许多不同的任务,在处理过程中发送电子邮件。

通过自定义类

发送电子邮件
public interface IEmailProvider
{
    void SendEmail(some params);
}
public class EmailProvider : IEmailProvider
{
    private readonly IEmailConfig _config;

    public EmailProvider(IEmailConfig config)
    {
        _emailConfig = emailConfig;
    }

    public void SendEmail(some params)
    {
        // send the email using the params
    }
}

我有一些使用电子邮件提供商的任务,每个任务都提供自己的IEmailConfig实现。

public class Task1 : ICommand
{
    public Task1(IEmailProvider emailProvider)
    {}
}

public class Task2 : ICommand
{
    public Task2(IEmailProvider emailProvider)
    {}
}

这是我设置的基本示例

public class TestInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        // Default email provider set up
        container.Register(Component.For<IEmailProvider>().ImplementedBy<EmailProvider>()
            .Named("DefaultEmailProvider")
            .LifeStyle.Transient);

        // Task 1 email config set up
        container.Register(Component.For<IEmailConfig>().ImplementedBy<Task1EmailConfig>()
            .Named("Task1EmailConfig"));

        // Task 2 email config set up
        container.Register(Component.For<IEmailConfig>().ImplementedBy<Task2EmailConfig>()
            .Named("Task2EmailConfig"));

        // Task 1 set up
        container.Register(Component.For<ICommand>().ImplementedBy<Task1>()
            .Named("Task1Command"));


        // Task 2 set up
        container.Register(Component.For<ICommand>().ImplementedBy<Task2>()
            .Named("Task2Command"));
    }
}

有没有办法可以在解决每个ICommand实现时做出决定,将IEmailConfig的哪个实现传递给EmailProvider类的构造函数?

目前,我使用ServiceOverride功能为每项任务注册了EmailProvider实例。这意味着对于每个需要发送电子邮件的任务,我必须几乎复制电子邮件提供商的设置,这是必需的配置。我最终得到了一些清单...

Component.For<IEmailConfig>()
    .ImplementedBy<Task1EmailConfig>()
    .Named("Task1EmailConfig"));

Component.For<IEmaiProvider>()        
    .ImplementedBy<EmailProvider>)
    .Named("Task1EmailProvider")
    .DependsOn(ServiceOverride.ForKey("config").Eq("Task1Config"));

Component.For<ICommand>()
    .ImplementedBy<Task1>()
    .DependsOn(ServiceOverride.ForKey("emailProvider").Eq("Task1EmailProvider")));

每项任务都会重复。

IEmailProvider实现始终是相同的,只有传入的IEmailConfig才会针对每个不同的任务进行更改。我不禁想到,到目前为止我必须有一个更简洁的解决方案。

1 个答案:

答案 0 :(得分:1)

我认为有几个handler selectors可以满足您的需求。一个用于IEmailProvider,另一个用于ICommand。

IEmailProvider可以检查被激活的IEmailProvider的名称(如“Task1EmailProvider”)并剥离“Provider”并添加“Config” - 这将为您提供密钥“Task1EmailConfig”,可用于解析特定的IEmailConfig对象。

同样,为ICommand做同样的事情。它将依赖于您一致地命名您的IEmailConfig,但它将消除您现在正在进行的所有手动连接。