2014-08-30 213 views
1

我一直在ASP.NET MVC中使用依賴注入的方式,我已經在下面的代碼中解釋,但我不知道如果這是正確的和標準的方式來做到這一點。所以我只想知道我在做什麼是錯誤的,或者是否有更好更專業的方式來做到這一點。在ASP.NET MVC依賴注入

public interface IService { 
    public Boolean AddRecord(Object _Model); 
} 

public class Employee: IService { 
    DataBase Context = new DataBase(); 
    public Boolean AddRecord(Object _Model) { 
     Context.Add((EmployeeModel) _Model); 
     return Context.SaveChanges() != 0; 
    } 
} 

public class DataController: Controller { 
    IService service; 
    public DataController(IService service) { 
     this.service = service; 
    } 

    public ActionResult AddRecord(Object _Model, String Caller) { 
     if (service.Add(_Model)) { 
      TempData["Result"] = "Data Added"; 
      return RedirectToAction(Caller); 
     } 
     TempData["Result"] = "Please try again"; 
     return View (Caller, _Model); 
    } 
} 

當我想用用DI控制器,我做的:(這是要消耗DataController類正道)

public class TestController: Controller { 
     public ActionResult Index() { 
      return View(); 
     } 

     public ActionResult TestIt (EmployeeModel _Model) { 
      DataController DC = new DataController(new Employee()); 
      return DC.AddRecord(_Model, "../Test/TestIt"); 
     } 
} 
+0

您已經在DataController中注入了一個依賴項。對於其他控制器來說,同樣的事情,我的意思是,不要在其他控制器中實例化DataController,而只需在構造函數中放置依賴關係。 – 2014-08-30 12:25:26

+0

當然,請看下面的答案。 – 2014-08-30 12:32:35

+1

你有下面的概念 - 依賴注入/反轉正是你在這裏展示的。另一方面,控制反轉是你下一步應該研究的。有很多容器爲你提供這個 - 有些甚至直接插入到MVC中(我們使用Ninject)。控制反轉不需要你完全實例化你的依賴關係。 – 2014-08-30 13:06:47

回答

1

你必須依賴注入/反轉的一般概念了。也就是說,你已經瞭解,而不是這樣的:

public class Example { 
    public void SomeFunc() { 
     var service = new Service(); 
     service.DoStuff(); 
    } 
} 

..你做到這一點:

public class Example { 
    private readonly IService _service; 

    public Example(IService service) { 
     _service = service; 
    } 

    public void SomeFunc() { 
     _service.DoStuff(); 
    } 
} 

..和您通過調用代碼手動提供的依賴..如Controller

public HomeController : Controller { 
    [HttpGet] 
    public ActionResult Index() { 
     var example = new Example(new Service()); 
     example.SomeFunc(); 
     // .. the rest .. 
    } 
} 

所以,第一部分是依賴倒置。你已經將依賴鏈從上到下顛倒了下來。第二部分(上面的代碼塊)是依賴注入

注意在上面的代碼塊中,Controller沒有注入依賴關係。這是控制反轉的用武之地。

控制的

反轉是這樣一種模式,其中的代碼完全在當前正在運行的代碼決定它的功能如何。在這種情況下,它意味着某些外部代碼 - 在別的地方 - 決定如何爲控制器提供依賴關係。

(注意,我很熟悉Ninject - 所以下面的示例使用Ninject有很多其他可用的DI/IoC容器的使用。)

Ninject是一個框架,可以幫助這一點(很多其他)。 Ninject爲ASP.NET MVC提供了一個擴展,它可以爲你自動構建和提供控制器實例 - 以及你的依賴關係。

沒有提供關於使用Ninject的完整教程(我將作爲OP的練習留給Google),其基本原理是這樣的。

您聲明一個「模塊」,其中包含您的依賴關係的配置。使用上面的例子,你的模塊可能是這樣的:

public class YourModule : NinjectModule { 
    public override void Load() { 
     Bind<IExample>().To<Example>().InRequestScope(); 
     Bind<IService>().To<Service>().InRequestScope(); 
    } 
} 

這將線了一個IExample所有請求的Example,並IServiceService的一個實例。所以,你Controller將成爲:

public class HomeController : Controller { 
    private readonly IExample _example; 

    public HomeController(IExample example) { 
     _example = example; 
    } 

    [HttpGet] 
    public ActionResult Index() { 
     _example.SomeFunc(); 
     // .. the rest .. 
    } 
} 

的容器(在這種情況下,Ninject)看你外部代碼(在YourModule類),並確定IExample應該是什麼。它認爲你已經說過它應該是一個Example類的實例。Example也需要依賴類型IService。所以Ninject會再次看到YourModule並確定它應該是Service的一個實例。它繼續沿着對象層次結構走下去,直到它完成對象的構造。

希望這是有道理的 - 這肯定很難在文本中解釋這些概念。

我還沒有看過這個視頻(當我等待互聯網連接時,我正在運行真正非常糟糕的WiFi熱點!),所以我無法驗證它的質量,但快速的Google搜索將此設置轉換爲設置up Ninject和MVC:http://www.youtube.com/watch?v=w_MehI2qBTo

你肯定會從一些反轉控制和/或Ninject視頻的Googling中獲益,以瞭解它是什麼樣的框架。

重要的是要注意,像Ninject這樣的框架也可以控制範圍。在上面的例子中,我用InRequestScope來對付綁定。這意味着Ninject將在Web請求開始時實例化依賴項,並在之後進行處理。這消除了您擔心這一點的需要。

+0

Ninject似乎影響性能(甚至幾毫秒)並增加代碼中的不明確性,是嗎?我已經在stackoverdlow中發現了一些類似於builder.Registr 的類似方法,但是我的方法出了什麼問題,我想知道爲什麼人們想要使用你所描述的而不是那個。 – JAX 2014-08-30 13:53:01

+0

表現 - 是的。所有容器都基於反射 - 但大多數緩存它們的查找(取決於它們如何構建依賴關係)。歧義 - 沒有。是的,在這種設置中會發生一些「魔術」 - 但模糊性的定義在於模糊。一旦你看到你的控制器注入了依賴關係,你就會知道它發生在別的地方。 – 2014-08-30 13:56:19

+0

另外 - 你在做什麼基本上是一樣的。你的代碼和我的區別在於你試圖從另一個控制器中使用控制器。有了容器,MVC框架將會消耗你的控制器(它應該)。完全完成後,您將永遠不會看到用於實例化依賴項的'new'關鍵字。注意你的代碼做到了 - 我的沒有。 – 2014-08-30 13:57:35