C# 使用IoC容器以实现应用程序的可扩展性

C# 使用IoC容器以实现应用程序的可扩展性,c#,ioc-container,C#,Ioc Container,我知道有一个类似的问题,但我认为我的问题在这个问题上更进一步 我最近一直在开发一个应用程序,它已经投入生产大约一年了,没有任何问题,也没有真正的扩展计划。应用程序几乎没有依赖项,使用DI,但没有容器 现在,根据公司的指示,我正在将应用程序扩展到更广泛的范围,这使我实现了IoC容器的使用。这里的问题是在代码中添加一个容器的开销,我以前认为这是不需要的 在我前进的过程中,我的具体问题是: 在规划和编写可能不会扩展太多的小型应用程序时,我是否应该实现一个容器,以预期这些场景可能会出现,并且在这样的预期

我知道有一个类似的问题,但我认为我的问题在这个问题上更进一步

我最近一直在开发一个应用程序,它已经投入生产大约一年了,没有任何问题,也没有真正的扩展计划。应用程序几乎没有依赖项,使用DI,但没有容器

现在,根据公司的指示,我正在将应用程序扩展到更广泛的范围,这使我实现了IoC容器的使用。这里的问题是在代码中添加一个容器的开销,我以前认为这是不需要的

在我前进的过程中,我的具体问题是:

  • 在规划和编写可能不会扩展太多的小型应用程序时,我是否应该实现一个容器,以预期这些场景可能会出现,并且在这样的预期中,我最好从一开始就实现一个容器,这样扩展框架就已经存在了

  • 如果在扩展应用程序超出其原始意图时实现容器变得很麻烦,这是否是设计不佳的标志

  • 编辑:

    我在我的应用程序中广泛使用了可靠的原则(尽我所能)和接口。目前,问题更多地涉及到IoC容器的使用,而不是DI本身。前面提到的应用程序是roll your own DI样式,我正在添加一个容器,这就是问题所在

  • 我认为即使在最小的应用程序中使用DI也是有益的,并且几乎没有缺点(开销非常小)。使用容器可能总是比滚动自己的容器快(更不用说stabler了)

  • 理想情况下,如果您应用了坚实的原则,并针对接口而不是具体类型进行编程,那么您应该只需要修改组合根。这当然意味着您一直在使用没有容器的DI,并且有一个DIY解决方案。如果不是的话,那么转移到DI可能会有点困难


  • 我建议不要同时处理整个重构。以小的增量一步一步地做,然后边做边测试。这最有可能不破坏任何现有功能,并允许您发现应用程序总体设计中的错误

    我非常喜欢
    干净的代码
    ,尤其是
    YAGNI
    。“你不会需要它的”。如果项目中不需要DI,就不要使用它。如果单元测试需要DI,但不需要容器,请不要使用容器。简单是它自身的一种美德。让它尽可能简单

    如果为将来的可扩展性准备项目需要花费时间或金钱,那么现在就不要这样做。你以后可以付。因为未来可能永远不会到来。如果它真的发生了,它肯定不会像预期的那样,你的准备也不会像你想象的那样有用

    我曾经参与过一些项目,其中有很多“可扩展性”代码,您可以删除至少75%的源代码,所有必需的功能仍然存在。我可以想象项目经理会想,到底是什么花了这么长时间才实现了这样一个基本的功能。不要那样做。规划您的项目,获取您的需求并实施它们。如果扩展性是一项需求,那么规划它,评估它,让您的经理知道。我的猜测是,他们不太需要扩展性。他们宁愿有另一个工作计划


    也就是说,显然你在学习。如果它在时间或金钱上不花费任何东西,那么继续开发你的下一个程序,这样它可以更容易地被扩展。只需关注成本。

    1。在规划和编写可能不会扩展太多的小型应用程序时,我是否应该实现一个容器,以预期这些场景可能会出现,并且在这样的预期中,我最好从一开始就实现一个容器,这样扩展框架就已经存在了

    为什么不为将来的成功做好准备呢?好处很多,即使是在一个小应用程序中,额外的工作也很少

    2. Is it a sign of poor design if implementing a container when extending an application beyond its original intention becomes cumbersome?
    
    有些人可能会争辩说,由于没有使用容器,最初的设计很差。您可能会改进设计,因此如果做得正确,这不会是一件坏事。原意是什么??紧密耦合且难以测试?我说,继续你的想法


    顺便说一句,如果您目前没有免费使用接口,我建议现在是开始的好时机。

    比较手动注入和自动注入:

    (一)

    正如在另一个答案中提到的,在我看来,从一开始就使用容器来证明您的解决方案是一个好主意。然而,我强烈建议在这之后使用一个好的编码标准文档。为了说明这一点,请查看我在生产系统中看到的以下代码

    public class MyClass
    {
     IUnityContainer _container;
     public MyClass(IMyDependentInterface dpenedentclass, IUnityContainer container)
     {
     _container = container;
     //........
     }
    
     public void DoSomething()
     {
      var obj = _container.Resolve<ISomeOtherInterface>();
      obj.DoAction();    
     }    
    }
    
    公共类MyClass
    {
    IUnityContainer\U容器;
    公共MyClass(IMyDependentInterface dpenedentclass、IUnityContainer容器)
    {
    _容器=容器;
    //........
    }
    公共无效剂量测定法()
    {
    var obj=_container.Resolve();
    obj.DoAction();
    }    
    }
    
    不知不觉中这里建立了一个反模式(服务定位器?)。正如你所看到的,在这个世界上似乎没有防故障的设计。因此,不要犹豫,在您的编码标准文档中添加看似显而易见的内容

    (二)


    如果转移到自动注射是困难的,这是一个不好的迹象。它可以是设计,但决不能低估前一点所解释的糟糕的实现破坏设计的力量。

    我知道YAGNI会出现,这正是我提出这个问题的原因。我同意成本肯定是一个因素,但正如其他答案所述,向小型应用程序添加容器的开销很小