控制器中带参数的构造函数 - MVC

11

我读了一些有关IOC和Unity的文章,但是感到很困惑:(

所以回到基础知识,有人能告诉我下面的代码是做什么的吗?

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

public interface IStudent 
{
     // Some method
}

这段代码很基础,我试图从一个外行的角度来理解。它到底做了什么?

这是依赖注入构造函数注入风格。 - publicgk
4个回答

28
HomeController对Student有依赖,因为它将某些职责委托给了Student类。
一种实现方法是:
public HomeController()
{
    private Student _student;
    public HomeController()
    {
        _student = new Student();
    }
}
public class Student 
{
    // Some method
}

但是HomeController对Student类有一个强依赖关系。如果您想使用其他实现的Student(例如,在单元测试HomeController时想要模拟Student),您将不得不修改Student类或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接口(抽象),而不是Student类(实现)。
这符合面向对象编程原则:
按照接口编程,而不是按照实现编程。 依赖于抽象,而不是依赖于具体类。
此外,它现在具有软依赖性。它不再与Student类紧密耦合。它是松散耦合的。 现在,通常情况下,您不需要担心在实例化HomeController时应该传递哪个IStudent实现。只要您正确地向依赖注入容器(在您的情况下为Unity)注册正确的接口和类,它就会处理这个问题。
_container.Register<IStudent, Student>();

当需要一个新的HomeController实例时,容器将识别到需要一个IStudent实例。因此,在实例化HomeController类时,它将实例化已注册的IStudent实例并将其作为参数传递。
另外,请注意,您所指的是“依赖注入”(它是IoC的一种具体形式)。还有其他形式的IoC(例如回调、观察者模式等)。
编辑:不要忘记阅读关于DI的popular article

3
_container 是什么? - JAX
这是一个“依赖注入容器”。例如Unity(示例文章),Castle Windsor,StructureMap等。 - publicgk

2
在IoC中,您需要注册接口和实现该接口的类。因此,一旦注册,每当您有像上面那样的签名时,IoC将自动创建IStudent实现类的实例,并在初始化控制器时将其注入到对象中。这节省了声明成员所需的时间和精力。在上述情况下,您只需要声明一个,但可能会有更多的成员,所有这些成员都需要传递给控制器。一旦我们正确注册了这些,IoC就会在此后完成它的工作。事实上,我们可以决定注入成员的范围/生命周期。它可以是PerInstance / Per Request /或Singleton。
有几个IoC框架可供选择,取决于您想选择哪一个。

2
一般来说,它被称为类的依赖注入,想象一下一个类或者更准确地说是一个GOD类,它处理所有的事情,比如(验证用户输入、与数据库协调、生成HTML输出等),所以你把所有的代码放在一个地方,或者你可以说你使用单个类开发所有的软件,这不是很好吗?
答案取决于你组织事物的方式,如果你认为将事物组织到它应该属于的位置是有益的,那么你会看到上面的GOD类中的问题。
因此,在面向对象编程中,一个类应该只有一个改变的原因,但如果需要完成工作,则应该寻求服务的帮助。
而你的HomeController也在做同样的事情,因为它不想被过度工作,所以它要求Student对象处理学生。

1
当IOC解析器构造一个新的HomeController对象时,它将通过构造函数接收一个实现了IStudent接口的对象,该对象由IOC容器(您注册的那个)提供。
您可以在此处阅读有关构造函数注入的更多信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接