2013-03-11 86 views
3

我已经阅读IOC和Unity几篇文章,并得到了我的自我困惑:(构造与控制器参数 - MVC

所以回到基本能有人电话我下面的代码做什么

private IStudent _student; 
     public HomeController(IStudent student) 
     { 
      _student= student; 
     } 

public interface IStudent 
    { 
     // Some method 
    } 

伊茨基本的,但我试图从一个门外汉视图来了解什么上面完全相同的代码呢?

+0

这是[Dependency Injection](http://martinfowler.com/articles/injection.html)的[构造函数注入](http://martinfowler.com/articles/injection.html#injector.gif)风格。 – publicgk 2013-03-11 06:11:38

回答

15

HomeController中对学生一个依赖,因为它代表了一些责任Student类。实施

一种方法是:

public HomeController() 
{ 
    private Student _student; 
    public HomeController() 
    { 
     _student = new Student(); 
    } 
} 
public class Student 
{ 
    // Some method 
} 

但随后的HomeController对学生类依赖。如果你想使用学生的其他实现(例如想要在单元测试HomeController的时候模拟学生),该怎么办?你将不得不修改学生类或HomeController类(或使用其他一些不那么好的选择)。这意味着你的HomeController的是紧耦合到Student类。

另一种方法是你已经发布的代码:

public class HomeController 
{ 
    private IStudent _student; 
    public HomeController(IStudent student) 
    { 
     _student = student; 
    } 
} 
public interface IStudent 
{ 
    // Some method 
} 
public class Student : IStudent 
{ 
    // Implementation of some method 
} 

在这里,你可以通过在IStudent即任何实现在单元测试中,你可以通过IStudent的模拟对象,在实际代码将传递Student类的对象。所以你HomeController现在是依赖在IStudent接口(抽象)而不是在学生类(一个实现)。 这符合OOP原则:

编程为接口,而不是实现。

取决于抽象。不要依赖于具体的课程。

此外,它现在具有软依赖性。它不再与Student类紧密结合。它是松耦合。 现在,通常您不需要担心在实例化您的HomeController时应该通过哪个IStudent实现。这就是Depedency Injection Container(你的情况下的Unity)会照顾到的,只要你注册了正确的接口和类。

_container.Register<IStudent, Student>(); 

因此,当需要一个新的HomeController实例时,容器将识别需要一个IStudent实例。因此它将实例化IStudent的注册实例,并在实例化HomeController类时将其作为参数传递。

此外,请注意您所指的是'依赖注入'(这是IoC的一种特定形式)。还有其他形式的IoC(例如回调,观察者模式等)。

编辑: 不要忘了阅读DI上的popular article

+0

什么是_container? – JAX 2014-08-30 11:59:24

+0

这是一个'依赖注入容器'。例如。 Unity([示例文章](http://msdn.microsoft.com/en-us/library/dn178463(v = pandp.30).aspx)),Castle Windsor,StructureMap等 – publicgk 2014-09-01 11:10:21

1

IOC中,你需要注册这是实现该接口的接口和类。 所以一旦你那么只要注册你有签名像上面那样,IoC会自动创建一个IStudent实现类的实例,并在初始化控制器时将它注入到对象中。 它节省了宣布成员的时间和努力。在上面的例子中,你只需要声明一个,但它可能更多,并且可能需要更少的实例传递给控制器​​。 一旦我们完全正确地注册IoC,之后就会开展工作。事实上,我们可以决定注入成员的范围/生命周期。它可以是PerInstance/Per Request/Or Singleton。

有一些Saveral IoC框架可供您使用,您可以随意使用它。

2

一般来说,它被称为注入类的依赖关系,思考一个类或精确的GOD类,它处理所有的东西(验证用户输入,与数据库协调,生成HTML输出等),让你保持你所有的代码都在一个地方,或者你可以说你使用单个类来开发所有的软件,这不是很好吗?

答案取决于你组织事物的方式,你认为组织它所属的事物是有益的,而不是你在上面的GOD类中看到的问题。

所以在OOPS,单一类SHD方面必须改变单一的原因,但它需要得到比它做SHD采取的帮助服务工作。

和你的HomeController做,因为它不希望同样的事情被过度劳累,它已经要求学生对象来处理学生。

1

当一个新的HomeController目的通过IOC分解器构成,将需要的是实现由IOC容器(一个你注册)通过它的构造提供IStudent接口的对象。

你可以阅读更多关于Constructor Injection here.