编译时的依赖注入

时间:2017-05-05 09:34:16

标签: dependency-injection

为什么所有DI框架在应用程序启动之前检查运行时的所有依赖项?为什么不在编译时检查一下,有什么好处呢?

是否可以更改已部署应用程序中的依赖项? 例如,当应用程序启动时,它会通过电子邮件发送通知,但之后我们可以更改为通过短信发送而不停止应用程序吗?

1 个答案:

答案 0 :(得分:1)

根据定义,DI容器通过使用反射来工作,这意味着运行时元数据。如果您希望在编译时检查所有内容,则不应使用DI容器,而是手动连接依赖项。手动应用DI是一种常见的做法,称为Pure DI

  

但之后我们可以改变发送短信而不停止申请吗?

您似乎要求应用程序在保持运行的同时响应配置更改。有一些常见的模式可以让你实现这一目标。通常,您希望定义该应用程序的组件对象图(包含其依赖关系的行的类链)。虽然您可以根据请求创建此类图表,但图表的形状不应在以后更改。相反,您使用代理和复合等模式。例如,考虑以下接口和实现:

interface INotificationSender
{
    void Send(string message);
}

class MailNotificationSender : INotificationSender { ... }

class SmsNotificationSender : INotificationSender { ... }

我们可以按如下方式定义代理:

class ConfigBasedNotificationSenderProxy : INotificationSender
{
    private readonly INotificationSender mail;
    private readonly INotificationSender sms;

    public ConfigBasedNotificationSenderProxy(
        INotificationSender mail, INotificationSender sms)
    {
        this.mail = mail;
        this.sms = sms;
    }

    public void Send(string message)
    {
        bool sendThroughMail = ReadFromConfgWhereToSendTo();
        var sender = sendThroughMail ? this.mail : this.sms;
        sender.Send(message);
    }
}

您可以在应用程序启动时构建以下对象图:

var sender = new ConfigBasedNotificationSenderProxy(
    new MailNotificationSender(...)
    new SmsNotificationSender(...));

您也可以使用DI容器连接,也可以手动(Pure DI)连接。但是,我要在这里做的重点是,即使您需要更改应用程序在运行时的行为方式,也不需要重新连接应用程序。您应该能够通过使用代理实现来更改通过应用程序对象图的调用图。