dependency-injection - inversion of control containers and the dependency injection pattern




為什麼我需要一個IoC容器而不是簡單的DI代碼? (20)

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容器中,則可以解決CustomerService,並且所有子依賴項都將自動得到解決。

例如:

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.
}

我一直在使用依賴注入 (DI)一段時間,在構造函數,屬性或方法中註入。 我從來沒有覺得需要使用控制反轉 (IoC)容器。 然而,我讀得越多,我感受到社區使用IoC容器的壓力越大。

我使用了.NET容器,如StructureMapNInjectUnityFunq 。 我仍然無法看到IoC容器如何使我的代碼受益/改進。

我也害怕開始在工作中使用容器,因為我的許多同事都會看到他們不明白的代碼。 他們中的許多人可能不願意學習新技術。

請說服我說我需要使用IoC容器。 當我與工作中的其他開發人員交談時,我會用這些論據。


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

  • ...扔掉類型安全。 許多(所有?)IoC框架都會強制您執行代碼,如果您想確保所有內容都正確連接。 “嘿!希望我已經設置了一切,這樣我對這100個類的初始化不會失敗,拋出空指針異常!”

  • ...用全局變量來代碼你的代碼(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>();
    }
}

這也是有缺陷的,但不那麼明顯。 In Haskell the type of Foo() would be IO Foo but you really don't want the IO -part and is should be a warning sign that something is wrong with your design if you got it.

To get rid of it (the IO-part), get all advantages of IoC-frameworks and none of it's drawbacks you could instead use an abstract factory.

The correct solution would be something like

data Foo = Foo { apa :: Bar }

or maybe

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

and inject (but I wouldn't call it inject) Bar.

Also: see this video with Erik Meijer (inventor of LINQ) where he says that DI is for people who don't know math (and I couldn't agree more): http://www.youtube.com/watch?v=8Mttjyf-8P4

Unlike Mr. Spolsky I don't believe that people who use IoC-frameworks are very smart - I simply believe they don't know math.


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.


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.


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?


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.


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.


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.


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?


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..


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.


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.



使用容器主要是從命令式/腳本式的初始化和配置變為聲明式 。 這可能有幾個不同的有益效果:

  • 減少hairball主程序的啟動例程。
  • 啟用相當深的部署時間重新配置功能。
  • 使依賴注入式風格成為新工作阻力最小的路徑。

當然,可能會有困難:

  • 需要復雜啟動/關閉/生命週期管理的代碼可能不容易適應容器。
  • 您可能需要處理任何個人,流程和團隊文化問題 - 但是,這就是為什麼您要求......
  • 一些工具包正在迅速變得重量級,鼓勵對許多DI容器開始反彈的深度依賴。

在我看來, 你已經建立了自己的IoC容器 (使用Martin Fowler描述的各種模式),並問為什麼別人的實現比你的更好。

所以,你有一堆已經有效的代碼。 並且想知道為什麼你想用其他人的實現替換它。

考慮第三方IoC容器的優點

  • 你可以免費修復bug
  • 圖書館的設計可能比你的要好
  • 人們可能已經熟悉特定的圖書館
  • 圖書館可能比你的要快
  • 它可能有一些你希望實現的功能,但從來沒有時間(你有服務定位器嗎?)

缺點

  • 你會得到bug,免費:)
  • 圖書館的設計可能比你的更糟糕
  • 你必須學習一個新的API
  • 太多的功能,你永遠不會使用
  • 調試你沒有寫的代碼通常比較困難
  • 從以前的IoC容器遷移可能很乏味

所以,權衡你的利弊並作出決定。


在我看來,IoC的頭號優勢是能夠集中配置您的依賴關係。

如果你正在使用依賴注入,你的代碼可能看起來像這樣

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類,而不是IMHO,那麼更令人困惑的配置文件可以是這樣的:

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
}

然後,你的Static 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容器採用了一個簡單,優雅和有用的概念,並使它成為必須用200頁的手冊研究兩天的東西。

我個人對於IoC社區如何獲得Martin Fowler的一篇精美優雅的文章感到困惑,並將它變成了一堆通常具有200-300頁手冊的複雜框架。

我盡量不做評判(哈哈!),但我認為使用IoC容器的人是(A)非常聰明,(B)對那些不像他們那樣聰明的人缺乏同情心。 一切都對他們很有意義,所以他們很難理解許多普通程序員會發現這些概念混淆。 這是知識詛咒 。 了解IoC容器的人很難相信有人不理解它。

使用IoC容器最有價值的好處是您可以在一個地方配置一個配置開關,讓您在測試模式和生產模式之間切換。 例如,假設您有兩個版本的數據庫訪問類......一個版本積極記錄並進行了大量驗證(在開發過程中使用),另一個版本沒有日誌記錄或驗證,而且這些版本的生產速度非常快。 能夠在一個地方切換它們是很好的。 另一方面,這是一個相當簡單的問題,不需要IoC容器的複雜性就能以簡單的方式處理。

我相信,如果你使用IoC容器,坦率地說,你的代碼變得難以閱讀。 你必須查看哪些地方來弄清楚代碼要做什麼,至少增加一個。 在天堂的某個地方,一位天使在哭泣。


我是一位正在復甦的國際奧委會癮君子。 我發現現在大多數情況下很難證明使用IOC作為DI是合理的。 國際奧委會容器犧牲了編譯時間檢查,並據說作為回報,給你“簡單”的設置,複雜的生命週期管理,並在運行時實時發現依賴關係。 我發現編譯時間檢查和結果運行時魔術/異常的損失,在絕大多數情況下都是不值得的。 在大型企業應用程序中,他們可能會很難遵循正在發生的事情。

我不會購買集中化的論點,因為你可以很容易地集中靜態設置,也可以通過為應用程序使用抽象工廠並虔誠地將對象創建推遲到抽象工廠,即做適當的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();
        }
    }
}

你的容器配置是你的抽象工廠實現,你的註冊是抽象成員的實現。 如果您需要新的單例依賴項,只需將另一個抽象屬性添加到抽象工廠。 如果你需要一個臨時依賴項,只需添加另一個方法並將其註入為Func <>。

優點:

  • 所有設置和對象創建配置均集中。
  • 配置只是代碼
  • 編譯時間檢查使其易於維護,因為您不能忘記更新註冊。
  • 沒有運行時反射魔法

我建議懷疑論者給它下一個綠色領域項目,並誠實地問自己在哪一點你需要容器​​。 稍後您可以很容易地考慮IOC容器,因為您只需使用IOC容器配置模塊替換工廠實施。


我認為使用DI獲得IoC的大部分價值。 既然你已經這樣做了,其餘的好處是增量的。

您獲得的價值將取決於您正在使用的應用程序的類型:

  • 對於多租戶,IoC容器可以負責一些基礎設施代碼以加載不同的客戶端資源。 當您需要特定於客戶端的組件時,請使用自定義選擇器來處理邏輯,而不用擔心客戶端代碼。 您當然可以自己創建它,但這裡有一個IoC如何提供幫助的例子

  • 有了很多可擴展點,IoC可以用來從配置中加載組件。 這是一個常見的事情,但工具由容器提供。

  • 如果您想為某些交叉問題使用AOP, IoC將提供攔截方法調用的鉤子 。 這在項目上通常很少做,但IoC使它更容易。

我以前編寫過這樣的功能,但是如果我現在需要這些功能,我寧願使用預先構建和測試的工具(如果它適合我的體系結構)。

正如其他人所提到的,您也可以集中配置您想要使用的類。 雖然這可能是一件好事,但它的代價是誤導和復雜。 大多數應用程序的核心組件都不會被取代太多,所以折衷有點難以實現。

我使用了一個IoC容器,並且欣賞了這個功能,但不得不承認我已經註意到了這個折衷:我的代碼在類級別變得更加清晰,在應用級別變得更加清晰(即可視化控制流)。


為我使用IoC容器(我親自使用Ninject)的最大好處是消除了設置和其他類型的全局狀態對象的傳遞。

我不為Web編程,我是一個控制台應用程序,並且在對象樹的很多地方,我需要訪問由用戶指定的設置或元數據,這些設置或元數據是在對象樹的完全獨立的分支上創建的。 使用IoC,我只需告訴Ninject將Settings設置為單例(因為總是只有一個實例),在構造函數中請求Settings或Dictionary,然後它們會在我需要它們時奇蹟般地出現!

在不使用IoC容器的情況下,在需要它的對象實際使用它之前,我必須將設置和/或元數據傳遞給2,3,...,n個對象。

DI / IoC容器還有很多其他的好處,因為其他人在這裡已經詳細說明了,並且從創建對像到請求對象的想法可能會讓人大跌眼鏡,但使用DI對我和我的團隊非常有幫助,所以也許您可以添加它到你的武庫!







ioc-container