ASP.NET MVC中的依赖注入

时间:2014-08-30 12:18:36

标签: c# asp.net-mvc dependency-injection

我一直在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");
      }
}

1 个答案:

答案 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();
    }
}

这会将IExampleExampleIService的所有请求连接到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请求开始时实例化依赖关系 - 并在之后处理它。这使您不必担心这一点。