如何減少對控制器的注入依賴項的數量
我正在使用 MVC3、Entity Framework v4.3 Code First 和 SimpleInjector。我有幾個看起來像這樣的簡單類:
public class SomeThing { public int Id { get; set; } public string Name { get; set; } }我有另一個看起來像這樣的實體:
public class MainClass { public int Id { get; set; } public string Name { get; set; } public virtual AThing AThingy { get; set; } public virtual BThing BThingy { get; set; } public virtual CThing CThingy { get; set; } public virtual DThing DThingy { get; set; } public virtual EThing EThingy { get; set; } }每個 Thingy(目前)都有自己的 Manager 類,如下所示:
public class SomeThingManager { private readonly IMyRepository<SomeThing> MyRepository; public SomeThingManager(IMyRepository<SomeThing> myRepository) { MyRepository = myRepository; } }因此,我的 MainController 如下:
public class MainController { private readonly IMainManager MainManager; private readonly IAThingManager AThingManager; private readonly IBThingManager BThingManager; private readonly ICThingManager CThingManager; private readonly IDThingManager DThingManager; private readonly IEThingManager EThingManager; public MainController(IMainManager mainManager, IAThingManager aThingManager, IBThingManager bThingManager, ICThingManager cThingManager, IDThingManager dThingManager, IEThingManager eThingManager) { MainManager = mainManager; AThingManager = aThingManager; BThingManager = bThingManager; CThingManager = cThingManager; DThingManager = dThingManager; EThingManager = eThingManager; } ...various ActionMethods... }實際上,這個控制器中註入的依賴項是原來的兩倍。它聞起來臭臭的。當您還知道存在具有所有或大部分相同依賴項的 OtherController 時,氣味會更糟。我想重構它。
我已經對 DI 有足夠的了解,知道屬性注入和服務定位器不是好主意。
我無法拆分我的 MainController,因為它是一個單一的螢幕,需要通過點擊一個保存按鈕來顯示和編輯所有這些內容。換句話說,單個 post 操作方法可以保存所有內容(儘管我願意更改它,只要它仍然是單個 Save 按鈕)。這個螢幕是用 Knockoutjs 建構的,如果有影響的話,它會用 Ajax 文章保存。
我幽默地使用了環境上下文,但我並不肯定這是正確的方法。我也幽默地使用了注入 Facade。我也想知道我是否應該在這一點上實現一個命令架構。(以上所有內容不只是將氣味轉移到其他地方嗎?)
最後,也許獨立於上述三種方法,我是否應該使用一個具有顯式方法的 LookupManager,例如 GetAThings()、GetAThing(id)、GetBThings()、GetBThing(id) 等?(但是那個 LookupManager 需要注入幾個儲存庫,或者一種新型的儲存庫。)
除了我的想法之外,我的問題是,重申一下:重構此程式碼以減少注入依賴項的瘋狂數量的好方法是什麼?
使用命令架構是個好主意,因為這會將所有業務邏輯移出控制器,並允許您添加橫切關注點而無需更改程式碼。但是,這不會解決您的建構子過度注入問題。標準解決方案是將相關依賴項移動到聚合服務中。但是,我同意 Mark 的觀點,您應該看看unit of work pattern。
您是否考慮過使用工作單元設計模式?關於什麼是工作單元,有一篇很棒的 MSDN文章。那篇文章的摘錄:
在某種程度上,您可以將工作單元視為轉儲所有事務處理程式碼的地方。工作單位的職責是:
- 管理交易。
- 對數據庫的插入、刪除和更新進行排序。
- 防止重複更新。在 Unit of Work 對象的單一用法中,程式碼的不同部分可能會將同一個 Invoice
對象標記為已更改,但 Unit of Work 類只會
向數據庫發出單個 UPDATE 命令。
使用工作單元模式的價值在於將其餘程式碼從這些問題中解放出來,這樣您就可以專注於業務邏輯。
有幾篇關於這個的部落格文章,但我發現的最好的一篇關於如何實現它是here。還有一些其他的已經從這個網站here和here中提到過。
最後,也許獨立於上述三種方法,我是否應該使用一個具有顯式方法的 LookupManager,例如 GetAThings()、GetAThing(id)、GetBThings()、GetBThing(id) 等?(但是那個 LookupManager 需要注入幾個儲存庫,或者一種新型的儲存庫。)
工作單元將能夠處理所有這些,特別是如果您能夠為大多數數據庫處理需求實現通用儲存庫。您的標籤提到您正在使用 Entity Framework 4.3 對嗎?
希望這可以幫助!