【问题标题】:What is IOC and why would I want to use Castle Windsor etc in my MVC app? [duplicate]什么是 IOC,为什么我要在 MVC 应用程序中使用 Castle Windsor 等? [复制]
【发布时间】:2011-01-11 21:33:29
【问题描述】:

可能重复:
What is IOC? Need some practical code examples to illustrate

我听说过很多 IOC 联合,但我仍然不完全确定它是什么以及我为什么想要它。我幼稚的理解是它以某种方式让你控制,但我不确定是什么。

我知道 Castle Windsor 是 ASP.Net MVC 的流行产品,但我不明白它的作用。它似乎覆盖了 ASP.Net MVC 处理控制器请求的默认方式。

我正在使用 Fluent NHibernate 启动一个 MVC 应用程序并尝试对其进行配置,但所有帖子似乎也建议使用 Castle Windsor。

您能否准确解释一下 IOC 是什么以及我为什么要在 ASP.Net MVC 应用程序中使用 Castle Windsor?

谢谢

【问题讨论】:

标签: asp.net-mvc inversion-of-control castle-windsor ioc-container


【解决方案1】:

IOC is a design pattern 由 Martin Fowler 引入,它允许代码的不同部分之间的耦合较弱。因此,例如在 ASP.NET MVC 应用程序中,您可以使用 IOC 将控制器逻辑与数据访问逻辑分离。背后的想法是控制器不与存储库的特定实现一起使用,而是使用接口。实例化控制器以提供特定实现是代码的责任:因此称为控制反转 - 控制其依赖关系的不是组件,而是控件的消费者。

假设你已经定义了以下合约:

public interface IUsersRepository
{
    IEnumerable<User> GetAllUsers();
}

然后你可以有一个依赖于这个合约的控制器:

public class UsersController : Controller
{
    private readonly IUsersRepository _repository;
    public UsersController(IUsersRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index()
    {
        var users = _repository.GetAllUsers();
        return View(users);
    }
}

如您所见,UsersController 与获取用户的方式完全分离。它使用契约,实例化此控制器的代码负责提供存储库的特定实现。在 ASP.NET MVC 的情况下,此代码是控制器工厂。 ASP.NET MVC 中内置的默认控制器工厂使用反射来调用匹配控制器的默认构造函数。在这种情况下,没有默认构造函数。所以你需要一个自定义的控制器工厂。这是温莎城堡comes into action

既然您的控制器已与存储库的特定实现分离,您将获得另一个非常重要的好处:您可以独立地对其进行单元测试,而无需依赖任何东西。您可以简单地模拟/替换此存储库并仅对控制器逻辑进行单元测试。

【讨论】:

  • @Darin - 我认为 - IoC 日期早于 Martin Fowler,请参阅此链接 betaversion.org/~stefano/linotype/news/38
  • 假设您刚刚拥有 public UsersController() 并且在该构造函数中您设置了一个私有存储库变量,该变量等于 UsersREpository 的新实例,这有什么不同?我想你不会需要温莎城堡
  • @Jon,是的,但这意味着您将此控制器绑定到存储库的特定实现 => 它将由控制器决定它使用什么实现,并且无法更改。此外,不可能单独对该控制器进行单元测试,这是一个重要方面。
  • @Jon,在我的示例中,我不依赖于特定的实现。我被绑定在一个合同上。这是代码的不同层之间可能存在的最弱耦合。耦合越弱,代码的可重用性就越高。经常发生变化的是实施,而不是合同,或者至少如果您正确设计您的应用程序并提前考虑好它应该是这样的。
  • @Jon,很抱歉,但我担心我不擅长解释,我想我不能比这更好地解释它了。也许您可以阅读 Martin Fowler 的文章并尝试更好地理解它。确实,当您一开始还没有实践这种面向合同的开发时,您不会立即明白这一点。但是相信我的实践和经验,你会明白的。试着把它放到一些现实世界的项目中。你会看到它有多有趣:-)
【解决方案2】:

非技术翻译!

假设您有一盒需要使用的螺丝刀。十字头螺丝刀、十字头磁性螺丝刀和可换头电磁螺丝刀。

当你刚开始工作时,你的工具箱里只有带十字头的螺丝刀,每次你需要把东西拧在一起时,你总是会使用这个工具。

后来,当您尝试向下拧螺丝时,您意识到螺丝从头部脱落的问题,因此您改用带有磁头的螺丝刀。

很久以后,您就可以买得起带有所有花里胡哨的神气的电动螺丝刀,并且您的效率大大提高了!

每个螺丝刀都实现了 IScrewDriver 接口,包括拧螺丝和拧螺丝的方法。在现实世界中很容易选择要使用的螺丝刀,在您的代码中,如果您在许多不同的地方创建 CrossHeadScrewdriver 类,则必须更改大量代码如果您想改用 ElectricScrewdriver

通过控制反转,您可以在代码的一处指定当您需要 IScrewDriver 时,它应该使用 ElectricScrewDriver 突然间,更换螺丝刀变得和现实世界一样简单!

【讨论】:

  • 很好的解释,谢谢。
  • 不完全准确,这个例子解释的是工厂模式。 IoC 模式表示您没有选择特定的 IScrewDriver 实例,而是其他人选择了实现并将其交给您。我想这很微妙:你打电话给工厂不是为了得到什么,而是工厂打电话给你是为了给你一些东西。
【解决方案3】:

除非您尝试,否则 IoC 尤其是温莎城堡不会帮助您。概念在MVC 2 in Action book 中有很好的描述。这是引用:

构建时的一种常用技术 申请就是通过申请 依赖于构造函数 控制器。通过利用各种 工具,我们可以自动接线 这些依赖项并提供 不用写的论据 平凡的,重复的代码。启用 这对于我们的控制器,我们需要 负责创建它们...

...

控制反转原理和依赖注入

通常当代码执行其他 代码,有一个线性流 创建和执行。例如, 如果我有一个依赖于的课程 另一个类,我将创建它 使用 new 运算符进行类,然后 通过调用方法来执行类。 如果我使用控制反转 (IoC), 我仍然会调用类的方法, 但我需要一个实例 类传递给我的构造函数。在 这种方式,我让出控制 定位或创建我的依赖项 调用代码。依赖注入 (DI) 是注入 依赖于依赖的类 就可以了。

经常互换使用,IoC 和 DI 产生松散耦合的代码和 经常与接口一起使用。和 接口,类声明 依赖项作为接口 构造函数参数。调用代码 然后找到适当的类和 在构建时传递它们 类。

IoC 容器开始发挥作用 协助管理这项技术 通过应用程序使用时。 有很多 IoC 容器可用于 从中选择,但在此的最爱 时间似乎是 StructureMap (http://structuremap.sourceforge.net), Ninject (http://ninject.org), 和 温莎城堡 (www.castleproject.org/container)。 控制器可以利用依赖 通过声明他们的注入 依赖作为构造函数 参数。这反转了控制 以便调用者负责 提供类的依赖项, 而不是类构造 具体实例本身。它允许 您将控制器与 其依赖项的具体实例 (例如存储库或服务)。 这很解放,更不用说 它有助于促进解耦 单元测试。

当我们要求 构造函数中的依赖项,我们 称之为构造函数注入。有 另一种称为属性的技术 注射,但不是很明显 这些依赖项是必需的 让对象完成它的工作。国际奥委会 工具通常可以两者兼得,但是 构造函数注入是首选 所需的依赖项。

【讨论】:

    猜你喜欢
    • 2014-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    相关资源
    最近更新 更多