2017-04-27 56 views
0

通常,操作方法將與像這樣結束:如何將依賴關係注入模型?

return View(new Model()); 

但如果我的模型都將有服務注入,它不會有一個默認的構造函數。因此,它必須是這樣的:

return View(new Model(new Service()); 

但如果服務有依存關係它會更是這樣的:

return View(new Model(new Service(new Repository()))); 

...它開始變得荒謬。這不是IoC容器的用途嗎?所以,我會忍不住寫更多的東西是這樣的:

return View(container.Resolve<IModel>()); 

,但爲了得到container它必須被注入到我的控制,我聽說injecting the container itself is an anti-pattern

那麼正確的方法是什麼?當我從操作方法返回視圖時,如何將我的依賴關係傳遞給我的模型?

回答

0

我已經使用了在引導程序代碼中初始化的靜態容器對象,但有時我不得不在容器中傳遞一個參數。一些代碼味道,但想象一個具有很多依賴關係的過程。但是如果你在MVC中使用DI,你會自動注入容器,這就是我看到的模式(檢查出Autofac MVC)。

1

但如果我的模型都將有服務注入

防止讓你的視圖模型從擺在首位有依賴關係。視圖模型應該是啞數據容器,並且在控制器操作返回時它們應該完全構建。這簡化了視圖和模型,並完全防止了這種情況。

如果您真的想將依賴關係傳遞給視圖模型,應該沒有理由傳遞依賴關係的依賴關係。你只需要傳遞依賴關係,並且由於你的控制器是一個應用程序組件,它就會將該依賴注入到它的構造函數中。因此,它通常如下所示:

public class HomeController : Controller 
{ 
    private readonly IService service; 

    public HomeController(IService service) 
    { 
     this.service = service; 
    } 

    public ViewResult Index() 
    { 
     return View(new Model(this.service)); 
    } 
} 

由於HomeController將是由DI容器與它的依賴(這意味着Service將使用Repository被建)建成,你可以通過在service依賴而不必知道任何關於它的依賴關係。

我聽說注射容器本身是一種反模式。

這是正確的。在Composition Root之外使用Container是個不錯的主意。

1

你說得對。正確執行依賴注入會使代碼更清晰,但會添加混亂的代碼,進行注入和初始化。這正是DI框架到位的地方。他們的主要目標是處理像你一樣的情況 - 刪除混亂的構造函數注入代碼,而不需要沿着容器傳遞。有了這樣Ninject一個DI框架,你的代碼應該是這樣的:

IKernel kernel = new StandardKernel(); 
Bind<View>(); 
Bind<Model>(); 
Bind<Service>(); 
Bind<Repository>(); 
var view = kernel.Get<View>(); 

之間你會手工做什麼,什麼DI框架會做的是顯示在這兩篇文章中對比:

順便說一句,還有很多其他的好的DI框架。你不需要拿Ninject,他們的基本想法都是一樣的。