Dependency injection 使用IWindsorInstaller的动态构造函数注入

Dependency injection 使用IWindsorInstaller的动态构造函数注入,dependency-injection,castle-windsor,castle,Dependency Injection,Castle Windsor,Castle,我不确定这是否可行,但我想我还是会问这个问题 我有一个场景,我有许多不同的任务,在处理过程中发送电子邮件 通过自定义类发送电子邮件 public interface IEmailProvider { void SendEmail(some params); } public class EmailProvider : IEmailProvider { private readonly IEmailConfig _config; public EmailProvider(

我不确定这是否可行,但我想我还是会问这个问题

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

通过自定义类发送电子邮件

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"));
    }
}
公共类测试安装程序:IWindsorInstaller
{
public void安装(IWindsorContainer、IConfigurationStore)
{
//默认电子邮件提供程序设置
container.Register(Component.For().ImplementedBy()实现)
.命名(“DefaultEmailProvider”)
(生活方式,短暂),;
//任务1电子邮件配置设置
container.Register(Component.For().ImplementedBy()实现)
。命名为(“Task1EmailConfig”);
//任务2电子邮件配置设置
container.Register(Component.For().ImplementedBy()实现)
。命名为(“Task2EmailConfig”);
//任务1设置
container.Register(Component.For().ImplementedBy()实现)
。命名为(“任务1司令部”);
//任务2设置
container.Register(Component.For().ImplementedBy()实现)
。命名为(“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")));
Component.For()
.由()实施
。命名为(“Task1EmailConfig”);
用于()的组件
。实施人)
.Named(“Task1EmailProvider”)
.DependsOn(ServiceOverride.ForKey(“配置”).Eq(“任务1配置”));
用于()的组件
.由()实施
.DependsOn(ServiceOverride.ForKey(“emailProvider”).Eq(“Task1EmailProvider”));
每个任务都将复制这些内容

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

我想有两个解决方案可以满足你的需要。一个用于IEmailProvider,一个用于ICommand

IEmailProvider one可以检查正在激活的IEmailProvider的名称(如“Task1EmailProvider”),然后去掉“Provider”并添加“Config”——这将为您提供键“Task1EmailConfig”,可用于解析特定的IEmailConfig对象

同样,对ICommand的也要做同样的事情。它将依赖于您对IEmailConfig的命名的一致性,但它将消除您现在正在进行的所有手动布线。

我认为有两种方法可以满足您的需要。一个用于IEmailProvider,一个用于ICommand

IEmailProvider one可以检查正在激活的IEmailProvider的名称(如“Task1EmailProvider”),然后去掉“Provider”并添加“Config”——这将为您提供键“Task1EmailConfig”,可用于解析特定的IEmailConfig对象


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

我确实想尝试IHandlerSelector,只是不确定如何连接它。但正如您所说,基于约定的命名可能会起作用。我确实想尝试IHandlerSelector,只是不确定如何连接它。但正如您所说,基于约定的命名可能会起作用。