我一直在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 :(得分: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
和IService
的所有请求连接到Service
的实例。所以你的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搜索将此设置为设置Ninject和MVC:http://www.youtube.com/watch?v=w_MehI2qBTo
你肯定会从谷歌搜索一些控制反转和/或Ninject视频中受益,以了解它是什么样的框架。
重要的是要注意像Ninject这样的框架也可以控制范围。在上面的示例中,我使用InRequestScope
来对抗绑定。这意味着Ninject将在Web请求开始时实例化依赖关系 - 并在之后处理它。这使您不必担心这一点。