3

我对 Unity 和 IoC 有点陌生,但对 MVC 不熟悉。我一直在阅读和阅读有关将 Unity 与 MVC 结合使用的信息,而我一直看到的唯一真正有用的东西是能够通过控制器获得免费的 DI。

从这里开始:

    public HomeController() : this(new UserRepository())
    {
    }

    public HomeController(IUserRepository userRepository)
    {
        this.UserRepository = userRepository;
    }

对此:

    public HomeController(IUserRepository userRepository)
    {
        this.UserRepository = userRepository;
    }

基本上,允许我删除无参数构造函数。这很棒,而且我肯定会实现它,但对于所有关于 IoC 库的炒作来说,这似乎并不是那么好。使用 Unity 作为服务定位器的方式听起来很有吸引力,但许多人会认为这是一种反模式。

所以我的问题是,在服务定位问题和视图和过滤器的一些 DI 机会的情况下,我从使用 Unity 中还有什么收获吗?我只是想确保我不会错过一些美妙的东西,比如对所有类构造函数的免费 DI 支持。

编辑:

我了解将 Unity DI 与 MVC 控制器一起使用背后的可测试性目的。但我所要做的就是添加一个额外的小构造函数,nix Unity,然后我就可以进行同样的 UnitTest。当替代方案更简单时,注册存储库类型和拥有自定义控制器工厂的巨大好处在哪里?另一种选择是原生 DI。我想我真的想知道 Unity(或任何 IoC 库)除了不好的服务定位之外还有什么好处。免费的 Controller DI 真的是我从 Unity 获得的唯一东西吗?

4

6 回答 6

1

关于为什么 Service Locator 被认为是不好的(某些人),您可以阅读Mark Seeman 的这篇博文

回答你的问题What is so good in Unity我可以说,除了所有的可测试性、松散耦合和其他每个人都在谈论的等等,你可以使用像Unity 的拦截这样的很棒的功能,它允许做一些类似 AOP 的事情。我在最近的一些项目中使用过它并且非常喜欢它。强力推荐!

ps 似乎Castle WindsorDI 容器也具有类似的功能(称为拦截器)。其他容器 - 不确定。

于 2013-04-02T23:21:21.803 回答
1

一个好的 IoC 容器不仅会为您创建具体的类,它还会检查该类型与其他类型之间的耦合。如果有其他依赖项,它会解析它们并创建所有需要的类的实例。

你可以做一些花哨的事情,比如条件绑定。这是一个使用 Ninject(我首选的 IoC)的示例:

ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();

ninjectKernel.Bind<IValueCalculator>().To<IterativeValueCalculator().WhenInjectedInto<LimitShoppingCart>();

ninject 在这里所做的是在注入 LimitShoppingCart 时创建一个 IterativeValueCalculator 实例,并为任何其他注入创建一个 LinqValueCalulator 实例。

最大的好处是关注点分离(解耦)和可测试性。

于 2013-04-02T23:13:35.363 回答
1

除了测试(这是一个巨大的好处,不应低估),依赖注入允许:

可维护性:通过一次更改更改代码行为的能力。

如果您决定更改在不依赖注入的情况下跨所有控制器/服务等检索用户的类,则需要更新每个构造函数以及正在创建的任何其他随机新实例,前提是您记住每个实例的位置。DI 允许您更改一个定义,然后在所有实现中使用该定义。

范围:通过一行代码,您可以更改您的实现以创建一个单例,一个仅在每个新 Web 请求或每个新线程上创建的类

可读性:依赖注入的使用意味着你所有的具体类都定义在一个地方。作为进入项目的开发人员,我可以快速轻松地准确查看哪些具体类映射到哪些接口,并且知道没有隐藏的实现。这意味着我不仅可以更好地阅读代码,而且使我有信心根据代码进行开发

设计:我相信使用依赖注入有助于创建设计良好的代码。你自动编码到接口,你的代码变得更干净,因为你没有奇怪的代码块来帮助你测试

让我们不要忘记...

测试:测试是巨大的!依赖注入允许您测试您的代码,而无需专门为测试编写代码。好的,您可以创建一个新的构造函数,但是阻止其他任何人使用该构造函数来实现它不打算用于的目的。如果另一个开发人员在六个月后出现并将生产逻辑添加到您的“测试”构造函数中会怎样。好的,所以你可以做到,internal但生产代码仍然可以使用它。为什么要给他们选择权。

我在 IoC 框架方面的经验主要围绕着Ninject。因此,以上内容基于我对 Ninject 的了解,但是相同的原则在其他框架中应该保持相同。

于 2013-04-02T23:41:15.193 回答
0

主要的一点是你在某处有一个映射,它指定了 IUserRepository 的具体类型。您可能喜欢这样的原因是您可以创建一个 UnitTest 来指定 IUserRepository 的模拟版本并执行您的测试,而无需更改控制器中的任何内容。

于 2013-04-02T22:48:13.990 回答
0

主要是可测试性,但我建议看看 Ninject,它与 MVC 配合得很好。要获得 IOC 的全部好处,您应该将其与 Moq 或类似的模拟框架结合起来。

于 2013-04-02T22:54:11.160 回答
0

除了可测试性之外,我认为您还可以添加可扩展性作为优势之一。软件开发的最佳实践之一是“使用抽象,而不是实现”,虽然您可以通过多种方式做到这一点,但 Unity 提供了一种非常可扩展且简单的方法来实现这一点。通过使用它,您将创建抽象来定义您的组件必须遵守的合同。假设您想完全更改您的应用程序当前使用的存储库。使用 DI,您只需“交换”组件,而无需更改应用程序上的一行代码。如果您使用硬引用,您可能需要更改和重新编译您的应用程序,因为它外部的组件(在不同的层中)

因此,恕我直言,底线是,使用 DI 可以帮助您在应用程序中拥有可插拔组件并拥有SOLID应用程序设计

于 2013-04-02T23:10:15.303 回答