2017-03-27 50 views
0

我正在使用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注入(IUserDatabaseIProductDatabase等)自動所有的依賴?

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); 
    } 
} 
+0

你爲什麼想這樣做?這是一個糟糕的主意,因爲如果你改變你的依賴關係,你有多個地方可以編輯,並且你沒有這樣做的好處...... – Milney

+0

修改'Dependencies'類有一個構造函數,它需要所有的內部依賴和然後StructureMap將爲您處理注射。另外,如果你這樣做是因爲你有很多依賴關係,你可能有興趣去檢查https://github.com/jbogard/MediatR – haim770

+0

儘管在[Aggregate Service]後面抽象一組依賴關係很好(http ://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices),我想你在這裏錯過了一個抽象。爲了簡化「操作」,將這些依賴關係及其邏輯移入業務層更爲常見,並讓該業務組件以專爲Controller定製的方式返回數據。這種方式在控制器中幾乎沒有任何行爲。 – Steven

回答

0

由於@ haim770建議,你必須創建在你Dependencies類的構造函數是希望所有的依賴關係。

但是在這種情況下,您只需將問題從控制器移到您的Dependencies類。

// Dependencies of Controller 
class Dependencies { 
    public IUserDatabase UserDatabase { get; set; } 
    public IProductDatabase ProductDatabase { get; set; } 
    // more dependencies ... 

    public Dependencies(IUserDatabase userDatabase, IProductDatabase productDatabase) 
    { 
     UserDatabase = userDatabase; 
     ProductDatabase = productDatabase; 
    } 
} 

然後,您的容器代碼將工作。

var container = new Container(); 
var dependencies = container.GetInstance<Dependencies>(); 
相關問題