为什么我需要一个IoC容器而不是简单的DI代码?

我一直在使用dependency injection (DI)一段时间,注入或者在构造函数,属性或方法。 我从来没有觉得需要使用控制反转 (IoC)容器。 然而,我读得越多,我感受到社区使用IoC容器的压力越大。

我使用了.NET容器,如StructureMap , NInject , Unity和Funq 。 我仍然看不到IoC容器将如何使我的代码受益/改进。

我也害怕在工作中使用容器,因为我的许多同事都会看到他们不懂的代码。 他们中的许多人可能不愿意学习新技术。

请说服我,我需要使用一个IoC容器。 当我和我的同事在工作中交谈时,我会用这些论据。

哇,不能相信乔尔会赞成这个:

var svc = new ShippingService(new ProductLocator(), new PricingService(), new InventoryService(), new TrackingRepository(new ConfigProvider()), new Logger(new EmailLogger(new ConfigProvider()))); 

在此:

 var svc = IoC.Resolve<IShippingService>(); 

许多人没有意识到,你的依赖关系链可以嵌套,并很快手动连接起来很难。 即使有工厂,重复你的代码也是不值得的。

IoC容器可能很复杂,是的。 但是对于这个简单的例子,我已经certificate这很简单。


好的,让我们来certificate这一点。 比方说,你有一些实体或模型对象,你想绑定到一个智能用户界面。 这个智能UI(我们称之为Shindows Morms)希望你实现INotifyPropertyChanged,以便它可以改变跟踪和相应地更新UI。

“好吧,听起来不那么难”,所以你开始写作。

你从这开始:

 public class Customer { public string FirstName { get; set; } public string LastName { get; set; } public DateTime CustomerSince { get; set; } public string Status { get; set; } } 

结果是:

 public class UglyCustomer : INotifyPropertyChanged { private string _firstName; public string FirstName { get { return _firstName; } set { string oldValue = _firstName; _firstName = value; if(oldValue != value) OnPropertyChanged("FirstName"); } } private string _lastName; public string LastName { get { return _lastName; } set { string oldValue = _lastName; _lastName = value; if(oldValue != value) OnPropertyChanged("LastName"); } } private DateTime _customerSince; public DateTime CustomerSince { get { return _customerSince; } set { DateTime oldValue = _customerSince; _customerSince = value; if(oldValue != value) OnPropertyChanged("CustomerSince"); } } private string _status; public string Status { get { return _status; } set { string oldValue = _status; _status = value; if(oldValue != value) OnPropertyChanged("Status"); } } protected virtual void OnPropertyChanged(string property) { var propertyChanged = PropertyChanged; if(propertyChanged != null) propertyChanged(this, new PropertyChangedEventArgs(property)); } public event PropertyChangedEventHandler PropertyChanged; } 

这是令人厌恶的pipe道代码,我坚持认为,如果你手动编写这样的代码, 你就是从你的客户端窃取 。 有更好,更聪明的工作方式。

听说过这个词,工作更聪明,不难吗?

想象一下你们团队中的一些聪明人出现了,并说:“这是一个更简单的方法”

如果你的属性是虚拟的(冷静下来,那不是什么大不了的),那么我们就可以自动编织属性行为。 (这称为AOP,但不要担心名字,专注于它会为你做什么)

根据您使用的IoC工具,您可以执行如下所示的操作:

 var bindingFriendlyInstance = IoC.Resolve<Customer>(new NotifyPropertyChangedWrapper()); 

噗! 现在,所有该手册的INotifyPropertyChanged BS都会自动为您在所讨论的对象的每个虚拟属性设置器上自动生成。

这是神奇的吗? ! 如果你可以相信这个代码完成它的工作,那么你可以安全地跳过所有包装mumbo-jumbo的属性。 你有业务问题要解决。

IoC工具的其他一些有趣的用途是做AOP:

  • 声明性和嵌套数据库事务
  • 声明和嵌套工作单元
  • logging
  • 前/后条件(按合同devise)

我和你在一起,瓦迪姆。 IoC容器采用了一个简单,优雅和有用的概念,并使它成为你必须用200页的手册学习两天的东西。

我个人对于IoC社区如何看待Martin Fowler的一篇精美优雅的文章感到困惑,并把它变成了一堆复杂的框架,通常有200-300页的手册。

我尽量不要做出判断(哈哈!),但是我认为使用IoC容器的人是(A)非常聪明,(B)对那些不够聪明的人缺乏同情心。 一切都对他们有意义,所以他们很难理解许多普通程序员会发现这些概念混乱。 这是知识的诅咒 。 了解IoC容器的人很难相信有人不理解它。

使用IoC容器最有价值的好处是可以在一个地方configuration一个configuration开关,让您在testing模式和生产模式之间切换。 例如,假设您有两个版本的数据库访问类…一个版本积极logging并进行了大量的validation,您在开发过程中使用了这个版本;另一个版本没有logging或validation,而且生产的速度非常快。 能够在一个地方切换它们是很好的。 另一方面,这是一个相当简单的问题,容易处理,而不需要IoC容器的复杂性。

我相信,如果你使用IoC容器,坦率地说,你的代码变得难以阅读。 你需要考虑的地方是弄清楚代码要做什么,至less要有一个。 在天上的某个地方,一位天使在呼喊。

想必没有人强迫你使用DI容器框架。 您已经在使用DI来分离您的课程并提高可testing性,所以您将获得很多好处。 总之,你赞成简单,这通常是一件好事。

如果您的系统达到了手动DI变得杂乱的一个级别(也就是增加维护),那么要权衡DI容器框架的团队学习曲线。

如果您需要更多地控制依赖项生命周期pipe理(也就是说,如果您觉得需要实现Singleton模式),请查看DI容器。

如果您使用DI容器,请仅使用您需要的function。 跳过XMLconfiguration文件并在代码中进行configuration(如果足够的话)。 坚持构造器注入。 Unity或StructureMap的基础知识可以缩减为几页。

Mark Seemann在这篇博文中写道: 何时使用DI容器?

在我看来,IoC的头号益处是能够集中configuration你的依赖关系。

如果你正在使用dependency injection,你的代码可能看起来像这样

 public class CustomerPresenter { public CustomerPresenter() : this(new CustomerView(), new CustomerService()) {} public CustomerPresenter(ICustomerView view, ICustomerService service) { // init view/service fields } // readonly view/service fields } 

如果你使用了一个静态的IoC类,而不是这个,恕我直言,更混乱的configuration文件,你可以有这样的东西:

 public class CustomerPresenter { public CustomerPresenter() : this(IoC.Resolve<ICustomerView>(), IoC.Resolve<ICustomerService>()) {} public CustomerPresenter(ICustomerView view, ICustomerService service) { // init view/service fields } // readonly view/service fields } 

然后,你的静态IoC类将看起来像这样,我在这里使用Unity。

 public static IoC { private static readonly IUnityContainer _container; static IoC() { InitializeIoC(); } static void InitializeIoC() { _container = new UnityContainer(); _container.RegisterType<ICustomerView, CustomerView>(); _container.RegisterType<ICustomerService, CustomerService>(); // all other RegisterTypes and RegisterInstances can go here in one file. // one place to change dependencies is good. } } 

IoC容器也适用于加载深层嵌套的类依赖。 例如,如果您有以下代码使用dependency injection。

 public void GetPresenter() { var presenter = new CustomerPresenter(new CustomerService(new CustomerRepository(new DB()))); } class CustomerPresenter { private readonly ICustomerService service; public CustomerPresenter(ICustomerService service) { this.service = service; } } class CustomerService { private readonly IRespository<Customer> repository; public CustomerService(IRespository<Customer> repository) { this.repository = repository; } } class CustomerRepository : IRespository<Customer> { private readonly DB db; public CustomerRepository(DB db) { this.db = db; } } class DB { } 

如果将所有这些依赖关系加载到IoC容器中,则可以parsingCustomerService,并且所有子依赖项都将自动得到解决。

例如:

 public static IoC { private IUnityContainer _container; static IoC() { InitializeIoC(); } static void InitializeIoC() { _container = new UnityContainer(); _container.RegisterType<ICustomerService, CustomerService>(); _container.RegisterType<IRepository<Customer>, CustomerRepository>(); } static T Resolve<T>() { return _container.Resolve<T>(); } } public void GetPresenter() { var presenter = IoC.Resolve<CustomerPresenter>(); // presenter is loaded and all of its nested child dependencies // are automatically injected // - // Also, note that only the Interfaces need to be registered // the concrete types like DB and CustomerPresenter will automatically // resolve. } 

我是声明式编程的粉丝(看看我回答了多less个SQL问题),但是我看过的IoC容器对于他们自己的好处似乎太神秘了。

…或者IoC容器的开发人员不能写出清晰的文档。

…否则两者在某种程度上都是真实的。

我不认为IoC容器的概念是不好的。 但是,实现必须既强大(即灵活),足以在各种应用程序中有用,而且简单易懂。

可能是其中一个和六个中的六个。 一个真正的应用程序(而不是玩具或演示)必然是复杂的,考虑到许多angular落案例和例外情况。 要么在命令式代码中包含这种复杂性,要​​么在声明式代码中。 但是你必须在某个地方代表它。

使用容器主要是从命令式/脚本式的初始化和configuration变为声明式 。 这可能有几个不同的有益效果:

  • 减less毛球主程序启动例程。
  • 启用相当深的部署时间重新configurationfunction。
  • 使dependency injection的风格成为新工作阻力最小的path。

当然,可能有困难:

  • 需要复杂启动/closures/生命周期pipe理的代码可能不容易适应容器。
  • 你可能必须导航任何个人,stream程和团队文化问题 – 但是,那就是为什么你问…
  • 一些工具包正在迅速变得重量级,鼓励类似的深刻依赖,许多DI容器开始反弹。

这听起来像你已经build立了自己的IoC容器 (使用Martin Fowler描述的各种模式),并问为什么别人的实现比你的更好。

所以,你有一堆已经工作的代码。 并想知道为什么你想要replace别人的实现。

考虑第三方IoC容器的优点

  • 你可以免费修复错误
  • 图书馆的devise可能比你的要好
  • 人们可能已经熟悉了特定的图书馆
  • 图书馆可能比你的要快
  • 它可能有一些function,你希望你实现,但从来没有时间(你有一个服务定位?)

缺点

  • 你得到错误介绍,免费:)
  • 图书馆的devise可能比你的要糟糕
  • 你必须学习一个新的API
  • 太多的function,你永远不会使用
  • debugging你没写的代码通常比较困难
  • 从以前的IoC容器迁移可能是乏味的

所以,权衡你的利弊并作出决定。

我认为IoC的大部分价值是通过使用DI获得的。 既然你已经这样做了,其余的好处是增量的。

您获得的价值将取决于您正在使用的应用程序的types:

  • 对于多租户,IoC容器可以负责加载不同客户端资源的一些基础架构代码。 当您需要特定于客户端的组件时,请使用自定义select器来处理逻辑,而不用担心客户端代码。 你当然可以自己build立这个,但这里是一个IoC如何帮助的例子 。

  • 有很多可扩展点,IoC可以用来从configuration中加载组件。 这是一个常见的东西来build立,但工具是由容器提供的。

  • 如果你想使用AOP来解决一些交叉问题, IoC提供了拦截方法调用的钩子 。 这在项目上通常不太常见,但IoC使得它更容易。

我以前编写过这样的function,但是如果我现在需要这些function,我宁愿使用预先构build和testing的工具,如果它符合我的架构。

正如其他人所提到的,你也可以集中configuration你想要使用的类。 虽然这可能是一件好事,但这是以误导和复杂为代价的。 大多数应用程序的核心组件不会被取代太多,所以折衷有点难。

我使用一个IoC容器,并欣赏function,但不得不承认我已经注意到了这个折衷:我的代码在课堂上变得更加清晰,在应用程序层次上变得更加清晰(即可视化控制stream程)。

我是一个复苏的国际奥委会瘾君子。 我发现现在大多数情况下很难certificate使用IOC作为DI是合理的。 国际奥委会容器牺牲编译时间检查,并假设作为回报给你“简单”的设置,复杂的生命周期pipe理和在运行时间的依赖关系的飞行发现。 我发现编译时间检查和运行时间魔法/exception的损失是不值得在绝大多数情况下的钟声和哨声。 在大型企业应用程序中,他们可能会很难跟踪正在发生的事情。

我不会购买集中化的论点,因为你可以很容易地集中静态设置,也可以通过为你的应用程序使用一个抽象工厂,虔诚地把对象创build延迟到抽象工厂,也就是做适当的DI。

为什么不这样做静态无魔力DI:

 interface IServiceA { } interface IServiceB { } class ServiceA : IServiceA { } class ServiceB : IServiceB { } class StubServiceA : IServiceA { } class StubServiceB : IServiceB { } interface IRoot { IMiddle Middle { get; set; } } interface IMiddle { ILeaf Leaf { get; set; } } interface ILeaf { } class Root : IRoot { public IMiddle Middle { get; set; } public Root(IMiddle middle) { Middle = middle; } } class Middle : IMiddle { public ILeaf Leaf { get; set; } public Middle(ILeaf leaf) { Leaf = leaf; } } class Leaf : ILeaf { IServiceA ServiceA { get; set; } IServiceB ServiceB { get; set; } public Leaf(IServiceA serviceA, IServiceB serviceB) { ServiceA = serviceA; ServiceB = serviceB; } } interface IApplicationFactory { IRoot CreateRoot(); } abstract class ApplicationAbstractFactory : IApplicationFactory { protected abstract IServiceA ServiceA { get; } protected abstract IServiceB ServiceB { get; } protected IMiddle CreateMiddle() { return new Middle(CreateLeaf()); } protected ILeaf CreateLeaf() { return new Leaf(ServiceA,ServiceB); } public IRoot CreateRoot() { return new Root(CreateMiddle()); } } class ProductionApplication : ApplicationAbstractFactory { protected override IServiceA ServiceA { get { return new ServiceA(); } } protected override IServiceB ServiceB { get { return new ServiceB(); } } } class FunctionalTestsApplication : ApplicationAbstractFactory { protected override IServiceA ServiceA { get { return new StubServiceA(); } } protected override IServiceB ServiceB { get { return new StubServiceB(); } } } namespace ConsoleApplication5 { class Program { static void Main(string[] args) { var factory = new ProductionApplication(); var root = factory.CreateRoot(); } } //[TestFixture] class FunctionalTests { //[Test] public void Test() { var factory = new FunctionalTestsApplication(); var root = factory.CreateRoot(); } } } 

您的容器configuration是您的抽象工厂实现,您的注册是抽象成员的实现。 如果您需要一个新的单例依赖项,只需将另一个抽象属性添加到抽象工厂。 如果你需要一个瞬态的依赖,只需添加另一个方法,并将其注入为Func <>。

优点:

  • 所有设置和对象创buildconfiguration都是集中的。
  • configuration只是代码
  • 编译时间检查很容易维护,因为您不能忘记更新注册。
  • 没有运行时reflection魔法

我build议怀疑论者把它放在下一个绿色领域项目,诚实地问自己在什么时候你需要容器​​。 稍后您可以很容易地考虑IOC容器,因为您只需使用IOC容器configuration模块replace工厂实施。

为我使用IoC容器(我个人使用Ninject)的最大好处是消除了设置和其他types的全局状态对象的传递。

我不为networking编程,我是一个控制台应用程序,在对象树的很多地方,我需要访问用户指定的设置或元数据,这些设置或元数据是在完全独立的对象树分支上创build的。 有了IoC,我只需告诉Ninject将Settings设置为单例(因为总是只有一个实例),请求构造函数中的Settings或Dictionary …并在需要的时候奇迹般地出现!

在不使用IoC容器的情况下,在需要它的对象实际使用它之前,必须将设置和/或元数据传递给2,3,…,n个对象。

DI / IoC容器还有许多其他的好处,正如其他人在这里所详述的,从创build对象到请求对象的想法可以让人大跌眼镜,但是使用DI对我和我的团队非常有帮助,所以也许可以添加它到你的武库!

IoC框架非常好,如果你想…

  • 扔掉types安全。 许多(所有的)IoC框架都会强制你执行代码,如果你想确定所有的东西都正确地连接起来的话。 “嘿,希望我能把所有东西都build立起来,这样我对这100个类的初始化不会失败,抛出空指针exception!

  • 抛弃你的代码与全局(IoC框架都是关于改变全球状态)。

  • …编写蹩脚的代码与不清楚的依赖关系,很难重构,因为你永远不会知道什么取决于什么。

IoC的问题在于使用它们的人用来写这样的代码

 public class Foo { public Bar Apa {get;set;} Foo() { Apa = new Bar(); } } 

由于Foo和Bar之间的依赖关系是固定的,这显然是有缺陷的。 然后他们意识到最好是写代码

 public class Foo { public IBar Apa {get;set;} Foo() { Apa = IoC<IBar>(); } } 

这也是有缺陷的,但不那么明显。 在Haskell中, Foo()的types是IO Foo但是你真的不需要IO -part,如果你有了它,应该是一个警告标志,说明你的devise有什么问题。

为了摆脱它(IO部分),获得IoC框架的所有优点,而不是使用抽象工厂的缺点。

正确的解决scheme将是类似的

 data Foo = Foo { apa :: Bar } 

或者可能

 data Foo = forall b. (IBar b) => Foo { apa :: b } 

并注入(但我不会称之为注入)吧。

另外:与Erik Meijer(LINQ的发明者)一起看这个video,他说DI是不懂math的人(我完全同意): http : //www.youtube.com/watch?v = 8Mttjyf-8P4

与Spolsky先生不同,我不相信使用IoC架构的人非常聪明 – 我只相信他们不懂math。

I've found that correctly implementing Dependency Injection tends to force programmers to use a variety of other programming practices that help to improve the testability, flexibility, maintainability, and scalability of code: practices like the Single Responsibility Principle, Separations of Concerns, and coding against APIs. It feels like I'm being compelled to write more modular, bite-sized classes and methods, which makes the code easier to read, because it can be taken in bite-sized chunks.

But it also tends to create rather large dependency trees, which are far more easily managed via a framework (especially if you use conventions) than by hand. Today I wanted to test something really quickly in LINQPad, and I figured it'd be too much bother to create a kernel and load in my modules, and I ended up writing this by hand:

 var merger = new SimpleWorkflowInstanceMerger( new BitFactoryLog(typeof(SimpleWorkflowInstanceMerger).FullName), new WorkflowAnswerRowUtil( new WorkflowFieldAnswerEntMapper(), new ActivityFormFieldDisplayInfoEntMapper(), new FieldEntMapper()), new AnswerRowMergeInfoRepository()); 

In retrospect, it would have been quicker to use the IoC framework, since the modules define pretty much all of this stuff by convention.

Having spent some time studying the answers and comments on this question, I am convinced that the people who are opposed to using an IoC container aren't practicing true dependency injection. The examples I've seen are of practices that are commonly confused with dependency injection. Some people are complaining about difficulty "reading" the code. If done correctly, the vast majority of your code should be identical when using DI by hand as when using an IoC container. The difference should reside entirely in a few "launching points" within the application.

In other words, if you don't like IoC containers, you probably aren't doing Dependency Injection the way it's supposed to be done.

Another point: Dependency Injection really can't be done by hand if you use reflection anywhere. While I hate what reflection does to code navigation, you have to recognize that there are certain areas where it really can't be avoided. ASP.NET MVC, for example, attempts to instantiate the controller via reflection on each request. To do dependency injection by hand, you would have to make every controller a "context root," like so:

 public class MyController : Controller { private readonly ISimpleWorkflowInstanceMerger _simpleMerger; public MyController() { _simpleMerger = new SimpleWorkflowInstanceMerger( new BitFactoryLog(typeof(SimpleWorkflowInstanceMerger).FullName), new WorkflowAnswerRowUtil( new WorkflowFieldAnswerEntMapper(), new ActivityFormFieldDisplayInfoEntMapper(), new FieldEntMapper()), new AnswerRowMergeInfoRepository()) } ... } 

Now compare this with allowing a DI framework to do it for you:

 public MyController : Controller { private readonly ISimpleWorkflowInstanceMerger _simpleMerger; public MyController(ISimpleWorkflowInstanceMerger simpleMerger) { _simpleMerger = simpleMerger; } ... } 

Using a DI framework, note that:

  • I can unit-test this class. By creating a mock ISimpleWorkflowInstanceMerger , I can test that it gets used the way I anticipate, without the need for a database connection or anything.
  • I use far less code, and the code is much easier to read.
  • If one of my dependency's dependency's changes, I don't have to make any changes to the controller. This is especially nice when you consider that multiple controllers are likely to use some of the same dependencies.
  • I never explicitly reference classes from my data layer. My web application can just include a reference to the project containing the ISimpleWorkflowInstanceMerger interface. This allows me to break the application up into separate modules, and maintain a true multi-tier architecture, which in turn makes things much more flexible.

A typical web application will have quite a few controllers. All of the pain of doing DI by hand in each controller will really add up as your application grows. If you have an application with only one context root, which never tries to instantiate a service by reflection, then this isn't as big a problem. Nevertheless, any application that uses Dependency Injection will become extremely expensive to manage once it reaches a certain size, unless you use a framework of some kind to manage the dependency graph.

Whenever you use the "new" keyword, you are creating a concrete class dependency and a little alarm bell should go off in your head. It becomes harder to test this object in isolation. The solution is to program to interfaces and inject the dependency so that the object can be unit tested with anything that implements that interface (eg. mocks).

The trouble is you have to construct objects somewhere. A Factory pattern is one way to shift the coupling out of your POXOs (Plain Old "insert your OO language here" Objects). If you and your co-workers are all writing code like this then an IoC container is the next "Incremental Improvement" you can make to your codebase. It'll shift all that nasty Factory boilerplate code out of your clean objects and business logic. They'll get it and love it. Heck, give a company talk on why you love it and get everyone enthused.

If your co-workers aren't doing DI yet, then I'd suggest you focus on that first. Spread the word on how to write clean code that is easily testable. Clean DI code is the hard part, once you're there, shifting the object wiring logic from Factory classes to an IoC container should be relatively trivial.

Because all the dependencies are clearly visible, it promotes creating components which are loosely coupled and at the same time easily accessible and reusable across the application.

You don't need an IoC container.

But if you're rigorously following a DI pattern, you'll find that having one will remove a ton of redundant, boring code.

That's often the best time to use a library/framework, anyway – when you understand what it's doing and could do it without the library.

I just so happen to be in the process of yanking out home grown DI code and replacing it with an IOC. I have probably removed well over 200 lines of code and replaced it with about 10. Yes, I had to do a little bit of learning on how to use the container (Winsor), but I'm an engineer working on internet technologies in the 21st century so I'm used to that. I probably spent about 20 minutes looking over the how tos. This was well worth my time.

As you continue to decouple your classes and invert your dependencies, the classes continue to stay small and the "dependency graph" continues to grow in size. (This isn't bad.) Using basic features of an IoC container makes wiring up all these objects trivial, but doing it manually can get very burdensome. For example, what if I want to create a new instance of "Foo" but it needs a "Bar". And a "Bar" needs an "A", "B", and "C". And each of those need 3 other things, etc etc. (yes, I can't come up with good fake names 🙂 ).

Using an IoC container to build your object graph for you reduces complexity a ton and pushes it out into one-time configuration. I simply say "create me a 'Foo'" and it figures out what's needed to build one.

Some people use the IoC containers for much more infrastructure, which is fine for advanced scenarios but in those cases I agree it can obfuscate and make code hard to read and debug for new devs.

Dittos about Unity. Get too big, and you can hear the creaking in the rafters.

It never surprises me when folks start to spout off about how clean IoC code looks are the same sorts of folks who at one time spoke about how templates in C++ were the elegant way to go back in the 90's, yet nowadays will decry them as arcane. Bah !

In the .NET world AOP isn't too popular, so for DI a framework is your only real option, whether you write one yourself or use another framework.

If you used AOP you can inject when you compile your application, which is more common in Java.

There are many benefits to DI, such as reduced coupling so unit testing is easier, but how will you implement it? Do you want to use reflection to do it yourself?

So, it's been almost 3 years, eh?

  1. 50% of those who commented in favor of IoC frameworks don't understand the difference between IoC and IoC Frameworks. I doubt they know that you can write code without being deployed to an app server

  2. If we take most popular Java Spring framework, it is IoC configuration moved from XMl into the code and now look like this

`@Configuration public class AppConfig {

 public @Bean TransferService transferService() { return new TransferServiceImpl(accountRepository()); } public @Bean AccountRepository accountRepository() { return new InMemoryAccountRepository(); } 

} ` And we need a framework to do this why exactly?

Honestly I don't find there to be many cases where IoC containers are needed, and most of the time, they just add unneeded complexity.

If you are using it just for making construction of an object simpler, I'd have to ask, are you instantiating this object in more than one location? Would a singleton not suit your needs? Are you changing the configuration at runtime? (Switching data source types, etc).

If yes, then you might need an IoC container. If not, then you're just moving the initialization away from where the developer can easily see it.

Who said that an interface is better than inheritance anyway? Say you're testing a Service. Why not use constructor DI, and create mocks of the dependencies using inheritance? Most services I use only have a few dependencies. Doing unit testing this way prevents maintaining a ton of useless interfaces and means you don't have to use Resharper to quickly find the declaration of a method.

I believe that for most implementations, saying that IoC Containers remove unneeded code is a myth.

First, there's setting up the container in the first place. Then you still have to define each object that needs to be initialized. So you don't save code in initialization, you move it (unless your object is used more than once. Is it better as a Singleton?). Then, for each object you've initialized in this way, you have to create and maintain an interface.

Anyone have any thoughts on this?

You would need an IoC container if you needed to centralize the configuration of your dependencies so that they may be easily swapped out en mass. This makes the most sense in TDD, where many dependencies are swapped out, but where there is little interdependence between the dependencies. This is done at the cost of obfuscating the flow of control of object construction to some degree, so having a well organized and reasonably documented configuration is important. It is also good to have a reason to do this, otherwise, it is mere abstraction gold-plating . I have seen it done so poorly that it was dragged down to being the equivalent to a goto statement for constructors.

Here is why. The project is called IOC-with-Ninject. You can download and run it with Visual Studio. This example uses Ninject but ALL the 'new' statements are in one location and you can completely change how your application runs by changing which bind module to use. The example is set up so you can bind to a mocked version of the services or the real version. In small projects that may not matter, but in big projects it's a big deal.

Just to be clear, advantages as I see them: 1) ALL new statements in one location at root of code. 2) Totally re-factor code with one change. 3) Extra points for 'cool factor' 'cause it's… well: cool. :p

I will try to find why IOC might not be good for from my perspective.

As with everything else, IOC container (or as Einstein would put it I=OC^2) is a concept you have to decide for yourself if you need it or not in your code. Recent fashion outcry about IOC is only that, fashion. Don't fall for fashion, that is first. There are myriads of concepts out there you could implement in your code. First of all, I am using dependency injection since I have started programming, and learned the term itself when it was popularized under that name. Dependency control is a very old subject and it was addressed so far in trillions of ways, depending on what was decoupling from what. Decoupling everything from everything is a nonsense. The problem with IOC container is that it tries to be as useful as Entity Framework or NHibernate. While writing an object-relational mapper is simply a must as soon as you have to couple any database with your system, IOC container is not always necessary. So when IOC container is useful:

  1. When you have a situation with many dependencies you want to organize
  2. When you do not care about coupling your code with third-party product
  3. When your developers want to learn how to work with a new tool

1: It is not that often that you have so many dependencies in your code, or that you are aware of them early in design. Abstract thinking is useful when abstract thinking is due.

2: Coupling your code with third-party code is a HuGe problem. I was working with code that is 10+ years old and that was following at that time fancy and advanced concepts ATL, COM, COM+ and so on. There is nothing you can do with that code now. What I am saying is that an advanced concept gives an apparent advantage, yet this is cancelled on long run with the outdated advantage itself. It just had made all of it more expensive.

3: Software development is hard enough. You can extend it to unrecognizable levels if you allow some advanced concept to crop into your code. There is a problem with IOC2. Although it is decoupling dependencies, it is decoupling the logic flow as well. Imagine you have found a bug and you need to set a break to examine the situation. IOC2, as any other advanced concept, is making that more difficult. Fixing a bug within a concept is more difficult than fixing a bug in a plainer code, because when you fix a bug a concept must be obeyed again. (Just to give you an example, C++ .NET is constantly changing the syntax so much that you need to think hard before you refactor some older version of .NET.) So what is the problem with IOC? The problem is in resolving dependencies. The logic for resolving is commonly hidden in the IOC2 itself, written maybe in uncommon way that you need to learn and maintain. Will your third-party product be there in 5 years? Microsoft's was not.

"We know how" syndrome is written all over the place regarding IOC2. This is similar to automation testing. Fancy term and perfect solution at first glance, you simply put all your tests to execute over night and see the results in the morning. It is really painful to explain company after company what automated testing really means. Automated testing is definitely not a quick way of reducing the number of bugs which you can introduce overnight to increase the quality of your product. But, fashion is making that notion annoyingly dominant. IOC2 suffers the same syndrome. It is believed that you need to implement it in order your software to be good. EvErY recent interview I was asked if I am implementing IOC2 and automation. That is a sign of fashion: the company had some part of code written in MFC they will not abandon.

You need to learn IOC2 as any other concept in software. The decision if IOC2 needs to be used is within the team and the company. However, at least ALL above arguments must be mentioned before the decision is made. Only if you see that plus side outweighs negative side, you can make a positive decision.

There is nothing wrong with IOC2 except that it does solve only the problems it solves and introduces the problems it introduces. 没有其他的。 However, going against the fashion is very difficult, they have sweat mouth, the followers of anything. It is strange how none of them is there when the problem with their fanciness becomes apparent. Many concepts in software industry have been defended because they create profit, books are written, conferences held, new products made. That is fashion, usually short lived. As soon as people find something else they abandon it completely. IOC2 is useful but it shows the same signs as many other vanished concepts I have seen. I do not know if it will survive. There is no rule for that. You think if it is useful, it will survive. No, it does not go that way. One big rich company is enough and the concept can die within few weeks. 我们拭目以待。 NHibernate survived, EF came second. Maybe IOC2 will survive too. Do not forget that most concepts in software development are about nothing special, they are very logical, simple and obvious, and sometimes it is more difficult to remember the current naming convention than to understand the concept itself. Does the knowledge of IOC2 make a developer a better developer? No, because if a developer was not able to come up with a concept similar in nature to IOC2 then it will be difficult for him or her to understand which problem IOC2 is solving, using it will look artificial and he or she may start using it for sake of being some sort of politically correct.

Personally, I use IoC as some sort of structure map of my application (Yeah, I also prefer StructureMap 😉 ). It makes it easy to substitute my ussual interface implementations with Moq implementations during tests. Creating a test setup can be as easy as making a new init-call to my IoC-framework, substituting whichever class is my test-boundary with a mock.

This is probably not what IoC is there for, but it's what I find myself using it for the most..

IOC CONTAINER SOLVES A PROBLEM YOU MIGHT NOT HAVE BUT IT'S A NICE PROBLEM TO HAVE

http://kozmic.net/2012/10/23/ioc-container-solves-a-problem-you-might-not-have-but-its-a-nice-problem-to-have/

you do not need a framework to achieve dependency injection. You can do this by core java concepts as well. http://en.wikipedia.org/wiki/Dependency_injection#Code_illustration_using_Java

I realize this is a rather old post, but it seems to still be reasonably active, and I thought I'd contribute a couple of points that have not yet been mentioned in other answers.

I will say that I agree with the benefits of dependency injection, but I do prefer to construct and manage the objects myself, using a pattern not unlike that outlined by Maxm007 in his answer. I have found two main problems with using 3rd party containers:

1) Having a 3rd party library manage the lifetime of your objects "automagically" can lend itself to unexpected results. We have found that especially in large projects, you can have vastly more copies of an object than you expect, and more than you would if you were manually managing the lifecycles. I'm sure this varies depending on the framework used, but the problem exists nonetheless. This can also be problematic if your object holds resources, data connections, etc., since the object can sometimes live longer than you expect. So inevitably, IoC containers tend to increase the resource utilization and memory footprint of an application.

2) IoC containers, in my opinion, are a form of "black box programming". I have found that in particular, our less experienced developers tend to abuse them. It allows the programmer to not have to think about how objects should relate to each other or how to decouple them, because it provides them with a mechanism in which they can simply grab any object they want out of thin air. Eg, there may be a good design reason that ObjectA should never know about ObjectB directly, but rather than creating a factory or bridge or service locator, an inexperienced programmer will simply say "no problem, I'll just grab ObjectB from the IoC container". This can actually lead to increased object coupling, which is what IoC is supposed to help prevent.

Dependency Injection in an ASP.NET project can be accomplished with a few lines of code. I suppose there is some advantage to using a container when you have an app that uses multiple front ends and needs unit tests.