3

我有用C#編寫的Web API應用程序。我正在努力確保設計符合SOLID原則。因此,我使用Unity將依賴關係注入到我的控制器中。但是我想讓控制器執行的動作脫離控制器本身,所以他們基本上只是調用其他(通常是靜態的)對象的方法。例如:依賴注入/ SOLID憂慮

public class MyController : ApiController 
{ 
    private readonly ISomeCrossCuttingInterface _instance; 
    private readonly ILog _log; 

    public MyController(ISomeCrossCuttingInterface someInterface, ILog log) 
    { 
     _instance = someInterface; 
     _log = log; 
    } 

    [HttpPost] 
    [ActionName("MyAction")] 
    public RequestResponse MyAction(MyActionData actionData) 
    { 
     try 
     { 
      return MyActionUser(actionData); 
     } 
     catch (Exception ex) 
     { 
      _log.Error("MyAction error", ex); 
     } 
     return ...; 
    } 

    private RequestResponse MyActionUser(MyActionData actionData) 
    { 
     var responseObj = StaticClass.SomeMethod(_instance, actionData); 
     var responseObj2 = StaticClass2.SomeMethod(_instance, responseObj2); 
     return CreateMyActionResponse(responseObj2); 
    } 

    private RequestResponse CreateMyActionResponse(...) 
    { 
     ... 
    } 
} 

什麼我遇到一些焦慮過度是是否使用的對象執行工作(如StaticClass和StaticClass2以上)實際上應該被注入。目前他們不是。已經注入的對象是那些涉及橫切問題的對象,例如日誌記錄或數據訪問,或者被多個控制器使用。那麼爲什麼我不注入執行工作的對象呢?我認爲這些「內部」對象只用於執行與一個控制器相關的特定工作。也就是說,控制器的功能基本上已經被分解成一個負責任的對象,每個控制器擁有自己獨特的一組對象,可以完成控制器需要做的任何事情。然而,這是一個糟糕的設計?是否應該注入所有對象?任何輸入真的讚賞。

回答

5

使用SOLID原則被廣泛接受,它會使您的代碼更具可維護性,可測試性和靈活性。如果你使用這些原則中的一部分,最好不要使用它。

試着想想如果你想以某種方式改變你的靜態類會發生什麼。你能確信變化不會破壞你的控制器嗎?你可以爲你的靜態類進行單元測試,而對於你的控制器可以有單元測試,但是你需要集成測試來檢查它們是否一起工作。如果你注入你的靜態類,而不是,那麼你可以很容易地使單元測試檢查,該方法被調用,返回正確的結果,等

而且你真的不希望你的控制器在做這個邏輯,它應該是好的和精益的,所以把所有東西都放到服務中,讓服務處理邏輯,調用存儲庫等,然後將服務注入控制器。

+0

謝謝,這聽起來像一個更好的方法,我目前的代碼沒有聞到正確的(!)。該服務需要在我的Unity配置中進行設置,如下所示:container.RegisterType ()。這將讓統一知道爲這種依賴創建什麼類型。我需要找到的是我如何將LoginService的依賴關係傳遞給它。 – fhevol

+0

您可以通過使用'container.RegisterTypes',而不是使它更容易爲自己,這將掃描實現你的接口類的一組組件。您可以使用一個約定,這樣如果有一個'LoginService'實現的'ILoginService'那麼這就是它會自動通過注射來解決的類型。 http://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx – demoncodemonkey

1

好吧。

你似乎認爲你會想嘲笑你的存儲庫。以類似的方式,您可能也想爲StaticClass注入其他行爲。但是如果行爲是固定的,那就保持原樣。

如果你讓所有東西都注射,你會發現它會導致代碼膨脹。所以我的建議是不要使用控制反轉來吸引SOLID原理,而是用它來覆蓋實際的測試場景。

+0

感謝。我實際上是在嘲笑我的存儲庫,因爲這是一個將在雲中運行的應用程序(可能在AWS上)。只是最初把所有東西都拼湊在一起,我嘲笑了資源庫。 – fhevol

4

你不應該注入的唯一東西是穩定的第三方庫,你知道肯定不會改變,不需要測試性,可維護性,並行開發,可擴展性或後期綁定。

如果StaticClass實際上包含邏輯MyController爲什麼不包括它的方法作爲StaticClass的一部分?否則,它必須在另一層面上做其他事情(不同的關注點)。

我相信你已經在你的書架上有了這個優秀的資源,但可以肯定的是,我會在這裏提供一個鏈接: Dependency Injection in .NET(Mark Seemann)。

從我自己的親身經歷:如果你實際上是做一個小的應用,只是它的樂趣和你可能會拋出當它這樣做,只是有它的樂趣。在這裏和那裏使用依賴注入,編寫一些單元測試,看看它的感覺和掌握它。如果完美的話,你無法做到。 例如,您是否可以輕鬆地在控制檯和WPF/WinForms應用程序之間進行更改?什麼需要改變?您可以輕鬆地在兩個應用程序之間交換模塊嗎?嘗試編寫不同的ILog實現。也許你想在你的控制檯上使用你的日誌,也許你想在一些GUI,txt或xml文件中使用它們。改變你的代碼有多容易?鬆散耦合的代碼是整個關鍵點,並且依賴注入模式在這裏有所幫助。

+0

感謝您的建議。爲了說明使用靜態類的,我有一個使用一個靜態類來驗證登錄(獲得從倉庫中的數據,並檢查密碼)和第二靜態類來創建一個會話的LoginController(也保存在存儲庫中這個應用程序使用REST)。 – fhevol

+0

我已經修改了我的設計,謝謝您的輸入。感謝這本書的建議,非常感謝。 – fhevol