我正在使用structuremap.net作爲我的容器。我想傳遞一個類的所有依賴關係作爲依賴對象,而不是每個依賴關係的一個參數。structuremap:使用setter注入設置對象的所有屬性
// Dependencies of Controller
class Dependencies {
public IUserDatabase UserDatabase { get; set; }
public IProductDatabase ProductDatabase { get; set; }
// more dependencies ...
}
class Controller {
Dependencies _d;
Controller(Dependencies dependencies){
this._d = dependencies;
}
public ActionResult Action() {
var user = _this._d.GetUserById(10);
var product = _this._d.GetProductById(20);
// ...
}
}
如何設置通過structuremap建設類Dependencies
的實例時使用setter注入(IUserDatabase
,IProductDatabase
等)自動所有的依賴?
var container = new Container();
// How to configure this in a generic way?
var dependencies = container.GetInstance<Dependencies>();
編輯
第一個例子似乎並沒有說明爲什麼我要setter注入了一個完整的對象,爲什麼這不是一個糟糕的設計選擇。
我們有一個自定義的Web框架,它從ASP.NET MVC中採取了很多原則,但在很多方面也有所不同。和ASP.NET MVC一樣,我們也有控制器中的動作和控制器以及組動作。典型代碼如下所示:
class MyController {
public IUserDatabase _userDatabase;
public IProductDatabase _productDatabase;
public IRatingDatabase _ratingDatabase;
public ICommentsDatabase _commentsDatabase;
MyController(IUserDatabase userDatabase, IUserDatabase productDatabase, IRatingDatabase ratingDatabase, ICommentsDatabase commentsDatabase){
_userDatabase = userDatabase;
_productDatabase = productDatabase;
_ratingDatabase = ratingDatabase;
_commentsDatabase = commentsDatabase;
}
public ActionResult Action1(){
var user = _userDatabase.GetById(10);
var product = _productDatabase.GetById(20);
}
public ActionResult Action2() {
var ratings = _ratingDatabase.GetById(20);
var comments = _commentsDatabase.GetById(20);
}
}
此控制器有兩個操作。這些操作都沒有使用控制器的所有依賴關係。此外,通過構造函數注入將依賴關係傳遞給控制器還有很多噪音。
相反,我想直接將動作的依賴關係作爲參數傳遞給該動作。我們有我們自己的路線,很容易支持這一點。
class Action1Dependencies {
public IUserDatabase UserDatabase {get; set;}
public IProductDatabase ProductDatabase {get; set;}
}
class Action2Dependencies {
public IRatingDatabase RatingDatabase {get; set;}
public ICommentsDatabase CommentsDatabase {get; set;}
}
class MyController {
public static ActionResult Action1(Action1Dependencies d){
var user = d.UserDatabase.GetById(10);
var product = d.ProductDatabase.GetById(20);
}
public static ActionResult Action2(Action2Dependencies d) {
var ratings = d.RatingDatabase.GetById(20);
var comments = d.CommentsDatabase.GetById(20);
}
}
因此,我想打個電話一樣var dependencies = container.GetInstance<Action2Dependencies>();
,並必須通過setter注入StructureMap設置Action2Dependencies
所有屬性。
用C#7和tuples支持上面的代碼也可能可能成爲
class MyController {
public static ActionResult Action1((IUserDatabase UserDatabase, IProductDatabase ProductDatabase) d){
var user = d.UserDatabase.GetById(10);
var product = d.ProductDatabase.GetById(20);
}
public static ActionResult Action2((IRatingDatabase RatingDatabase, ICommentsDatabase CommentsDatabase) d) {
var ratings = d.RatingDatabase.GetById(20);
var comments = d.CommentsDatabase.GetById(20);
}
}
你爲什麼想這樣做?這是一個糟糕的主意,因爲如果你改變你的依賴關係,你有多個地方可以編輯,並且你沒有這樣做的好處...... – Milney
修改'Dependencies'類有一個構造函數,它需要所有的內部依賴和然後StructureMap將爲您處理注射。另外,如果你這樣做是因爲你有很多依賴關係,你可能有興趣去檢查https://github.com/jbogard/MediatR – haim770
儘管在[Aggregate Service]後面抽象一組依賴關係很好(http ://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices),我想你在這裏錯過了一個抽象。爲了簡化「操作」,將這些依賴關係及其邏輯移入業務層更爲常見,並讓該業務組件以專爲Controller定製的方式返回數據。這種方式在控制器中幾乎沒有任何行爲。 – Steven