【问题标题】:Why to use a IoC framework为什么要使用 IoC 框架
【发布时间】:2011-04-18 11:27:34
【问题描述】:

我一直在阅读有关控制反转框架的内容,但我只是在玩弄这个问题:“我到底为什么需要一个框架来做到这一点?”

不要误解我的问题...这种模式是我们程序员经常使用的,但是...一个功能齐全的框架可以做到这一点?

我一定遗漏了一些东西,这就是我发布问题的原因。我在网上看到了很多例子,我就是不明白。可能我脑子里被这个想法挡住了。

看一下 Ninject 主页的示例:

public class Samurai {
    public IWeapon Weapon { get; private set; }
    public Samurai(IWeapon weapon) {
        Weapon = weapon;
    }
}

public class WarriorModule : NinjectModule {
    public override void Load() {
        Bind< IWeapon >.To< Sword >();
    }
}

“武士”课程对我来说没问题。 “NinjectModule”框架对我来说似乎没有必要。

我假设稍后在代码中我们将创建新的“Samurai”实例,将“Sword”实例传递给它,类似于:

Samurai theWarrior = new Samurai(WarriorModule.GetInstance(IWeapon));//no coupling

可以替换为:

Samurai theWarrior = new Samurai(new Sword());//still no coupling

Samurai theWarrior = new Samurai(GetWeaponFromXML());//no coupling yet

我缺少什么?您能否介绍一下我的应用程序中可能需要 Ioc 框架的一些场景?

谢谢。

4 个答案后更新:我真的很喜欢从你们那里得到的所有答案。我刚刚阅读了这篇 dependency-injection-dissection/ 的帖子,那个家伙将它用于单元测试和您刚刚提供的 StackOverflow 链接,是的,我错过了大复杂性部分,所以让我自己自定义使用 IoC 框架。再次感谢。

我会投票给你的答案,但我只是收到一条橙色消息,说我不能。

感谢突出显示我发布的代码的人。

【问题讨论】:

  • 我建议通过highlighting and pressing ctrl-k 或在每行代码前插入四个空格来编辑您的问题以使代码块成为实际的代码块。
  • new Samurai(new Sword());//still no coupling 这里有一个紧耦合,你使用 new 。当你重构它时,你必须改变每个实例化剑的地方。

标签: ioc-container ninject


【解决方案1】:

这是代码示例的问题。它们要么很复杂,你还没有解释你的观点,要么它们很琐碎,然后看起来毫无意义。

WarriorModule 所做的是将具体类型绑定到接口,因此当另一个类需要该接口的实现时,它会通过 IoC 容器自动接收。具有依赖关系的类不依赖于具体类型,因此具有较低的耦合性和较高的可测试性。我想你已经知道了。

在您的替换场景中,Samurai 类不与剑类耦合,但调用代码仍然是。您可以将其推出另一个级别,但是该代码现在将具有依赖项,并且您的干预类现在必须编组所有依赖项。

IoC 容器为所有映射执行此操作,仅将其放在少数几个地方(模块类)。您的其余代码可以随意不关心,不依赖于具体类型。

希望对您有所帮助。

【讨论】:

  • 点赞此评论; “这就是代码示例的问题。它们要么很复杂,你还没有解释你的观点,要么它们很琐碎,然后看起来毫无意义。”我通常会对后者说更多。特别是对于 Ninject,给出的示例都没有证明它的使用是合理的,因为它们太简单了,并且没有展示任何使它值得超越手动 DI 的细节。
  • 如果你有一个好的设计,你根本没有太多的耦合。如果我在一个地方使用 XML 或代码定义布线,区别在哪里?
【解决方案2】:

我最近开始使用 Unity for IoC,毫无疑问,它让我的生活更轻松。

我将逐字粘贴我的代码,希望您觉得它有用。更有经验的人可能会给你更多。

另外,我发现阅读 Fowler 关于 DI 的论文很有用。

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        using (IUnityContainer container = new UnityContainer())
        {
            container

                .RegisterType<ILogger, StatSyncherFormView>(new myLife())

                // GUI
                .RegisterType<IStatSyncherView, StatSyncherFormView>()

                // Services
                .RegisterType<ISalesForceWebServices, SalesForceWebServices1>()

                .RegisterInstance(new SalesForceWebServices1(
                    "XXX", "XXX",
                   "https://login.salesforce.com/services/Soap/c/19.0/0DF70000000CfHq",
                    "https://na5-api.salesforce.com/services/Soap/s/19.0"))


                .RegisterType<ISalesForceService, SalesForceService1>()

                .RegisterType<IRestApiCall, RestApiCall1>()

                .RegisterType<IDirectTrackService, DirectTrackService1>()

                .RegisterType<IDAgentsService, DAgentsService1>()

                .RegisterType<IQuickBooksService, QuickBooksService1>();

            StatSyncherPresenter p = container.Resolve<StatSyncherPresenter>();

            Application.Run((Form)p.view);
        }
    }

我觉得最有用的事情之一是:

public class AnyClassCreatedByContainer
{
    [Dependency]
    public ILogger Logger { get; set; }
}

【讨论】:

    【解决方案3】:

    虽然Samurai theWarrior = new Samurai(new Sword()); 仍然没有耦合,但如果你想给你的应用程序中的所有武士一个&lt;insert favourite weapon here&gt;,你必须更改所有调用代码以更改为新武器,而使用 IoC 你需要更改它在一个地方,你所有的武士都会使用新武器。

    【讨论】:

      【解决方案4】:

      你的例子很简单,只有两层,但是当你有一个真实的例子时,它很快就会变得混乱:

      var form = new OrderEntryForm(
          new OrderService(
              new OrderReposity(
                  new DatabaseGateway(
                      new DataProviderFactory()))))
      

      IoC 容器可以为您完成所有接线工作,让您的生活更轻松。

      这是一个类似问题的示例,涉及所有细节: https://stackoverflow.com/questions/45191/ioc-explain-and-more-important-when-to-use-it/45197#45197

      【讨论】:

      • IoC 容器如何降低复杂性?我的意思是你仍然需要定义整个树,但必须使用另一种更容易出错的语言。
      猜你喜欢
      • 2010-12-23
      • 1970-01-01
      • 2010-09-21
      • 2021-10-23
      • 1970-01-01
      • 2019-04-13
      • 2017-12-04
      • 1970-01-01
      相关资源
      最近更新 更多