2017-05-05 116 views
-1

爲什麼所有DI框架應用程序之前,在運行時檢查所有的依賴開始?爲什麼不在編譯時檢查,這有什麼好處?依賴注入在編譯時

是否有可能改變部署的應用程序依賴? 例如,當應用程序啓動它通過電子郵件發送通知,但我們可以改變後通過短信發送而不停止應用程序?

+0

你似乎已經忽略了一點在使用DI框架...如果你在編譯的時候做到這一點,那麼你只是硬接線的依賴關係,這是不DI ... – Milney

+1

好了,你可以改變依賴已部署的應用程序中? – Romper

+0

這是一點是的。它還允許您根據只在運行時才知道的其他信息有條件地註冊不同的實現......這也使維護變得更加困難...... – Milney

回答

2

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容器連線,或者手動(純DI)。但是,我試圖在這裏指出的重要一點是,即使您需要更改應用程序在運行時的行爲方式,您也不需要重新連接應用程序。您應該可以使用代理實現來更改通過應用程序的對象圖的調用圖。

+0

已更新,其中包含有關在運行時更改應用程序行爲的信息。 – Steven