dependency-injection of - Why do I need an IoC container as opposed to straightforward DI code?




pattern laravel (25)

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

I've been using Dependency Injection (DI) for a while, injecting either in a constructor, property, or method. I've never felt a need to use an Inversion of Control (IoC) container. However, the more I read, the more pressure I feel from the community to use an IoC container.

I played with .NET containers like StructureMap, NInject, Unity, and Funq. I still fail to see how an IoC container is going to benefit / improve my code.

I'm also afraid to start using a container at work because many of my co-workers will see code which they don't understand. Many of them may be reluctant to learn new technology.

Please, convince me that I need to use an IoC container. I'm going to use these arguments when I talk to my fellow developers at work.



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 !


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.


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.


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


IoC Containers are also good for loading deeply nested class dependencies. For example if you had the following code using Depedency 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 { }

If you had all of these dependencies loaded into and IoC container you could Resolve the CustomerService and the all the child dependencies will automatically get resolved.

For example:

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

It sounds to me like you already built your own IoC container (using the various patterns which were described by Martin Fowler) and are asking why someone else's implementation is better than yours.

So, you have a bunch of code that already works. And are wondering why you would want to replace it with someone else's implementation.

Pros for considering a third-party IoC container

  • You get bugs fixed for free
  • The library design may be better than yours
  • People may be already familiar with the particular library
  • The library may be faster than yours
  • It may have some features you wish you implemented but never had time to (do you have a service locater?)

Cons

  • You get bugs introduced, for free :)
  • The library design may be worse than yours
  • You have to learn a new API
  • Too many features you will never use
  • It's usually harder to debug code you did not write
  • Migrating from a previous IoC container may be tedious

So, weigh your pros against your cons and make a decision.


Wow, can't believe that Joel would favor this:

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

over this:

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

Many folks don't realize that your dependencies chain can become nested, and it quickly becomes unwieldy to wire them up manually. Even with factories, the duplication of your code is just not worth it.

IoC containers can be complex, yes. But for this simple case I've shown it's incredibly easy.


Okay, let's justify this even more. Let's say you have some entities or model objects that you want to bind to a smart UI. This smart UI (we'll call it Shindows Morms) wants you to implement INotifyPropertyChanged so that it can do change tracking & update the UI accordingly.

"OK, that doesn't sound so hard" so you start writing.

You start with this:

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

..and end up with this:

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

That's disgusting plumbing code, and I maintain that if you're writing code like that by hand you're stealing from your client. There are better, smarter way of working.

Ever hear that term, work smarter, not harder?

Well imagine some smart guy on your team came up and said: "Here's an easier way"

If you make your properties virtual (calm down, it's not that big of a deal) then we can weave in that property behavior automatically. (This is called AOP, but don't worry about the name, focus on what it's going to do for you)

Depending on which IoC tool you're using, you could do something that looks like this:

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

Poof! All of that manual INotifyPropertyChanged BS is now automatically generated for you, on every virtual property setter of the object in question.

Is this magic? YES! If you can trust the fact that this code does its job, then you can safely skip all of that property wrapping mumbo-jumbo. You've got business problems to solve.

Some other interesting uses of an IoC tool to do AOP:

  • Declarative & nested database transactions
  • Declarative & nested Unit of work
  • Logging
  • Pre/Post conditions (Design by Contract)

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.



The biggest benefit of using IoC containers for me (personally, I use Ninject) has been to eliminate the passing around of settings and other sorts of global state objects.

I don't program for the web, mine is a console application and in many places deep in the object tree I need to have access to the settings or metadata specified by the user that are created on a completely separate branch of the object tree. With IoC I simply tell Ninject to treat the Settings as a singleton (because there is always only one instance of them), request the Settings or Dictionary in the constructor and presto ... they magically appear when I need them!

Without using an IoC container I would have to pass the settings and/or metadata down through 2, 3, ..., n objects before it was actually used by the object that needed it.

There are many other benefits to DI/IoC containers as other people have detailed here and moving from the idea of creating objects to requesting objects can be mind-bending, but using DI was very helpful for me and my team so maybe you can add it to your arsenal!


In my opinion the number one benefit of an IoC is the ability to centralize the configuration of your dependencies.

If you're currently using Dependency injection your code might look like this

public class CustomerPresenter
{
  public CustomerPresenter() : this(new CustomerView(), new CustomerService())
  {}

  public CustomerPresenter(ICustomerView view, ICustomerService service)
  {
    // init view/service fields
  }
  // readonly view/service fields
}

If you used a static IoC class, as opposed to the, IMHO the more confusing, configuration files, you could have something like this:

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
}

Then, your Static IoC class would look like this, I'm using Unity here.

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

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.


I think most of the value of an IoC is garnered by using DI. Since you are already doing that, the rest of the benefit is incremental.

The value you get will depend on the type of application you are working on:

  • For multi-tenant, the IoC container can take care of some of the infrastructure code for loading different client resources. When you need a component that is client specific, use a custom selector to do handle the logic and don't worry about it from your client code. You can certainly build this yourself but here's an example of how an IoC can help.

  • With many points of extensibility, the IoC can be used to load components from configuration. This is a common thing to build but tools are provided by the container.

  • If you want to use AOP for some cross-cutting concerns, the IoC provides hooks to intercept method invocations. This is less commonly done ad-hoc on projects but the IoC makes it easier.

I've written functionality like this before but if I need any of these features now I would rather use a pre-built and tested tool if it fits my architecture.

As mentioned by others, you can also centrally configure which classes you want to use. Although this can be a good thing, it comes at a cost of misdirection and complication. The core components for most applications aren't replaced much so the trade-off is a little harder to make.

I use an IoC container and appreciate the functionality but have to admit that I've noticed the trade-off: My code becomes more clear at the class level and less clear at the application level (i.e. visualizing control flow).


IoC frameworks are excellent if you want to...

  • ...throw away type safety. Many (all?) IoC frameworks forces you to execute the code if you want to be certain everything is hooked up correctly. "Hey! Hope I got everything set up so my initializations of these 100 classes won't fail in production, throwing null-pointer exceptions!"

  • ...litter your code with globals (IoC frameworks are all about changing global states).

  • ...write crappy code with unclear dependencies that's hard to refactor since you'll never know what depends on what.

The problem with IoC is that the people who uses them used to write code like this

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

which is obviously flawed since the dependency between Foo and Bar is hard-wired. Then they realized it would be better to write code like

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

which is also flawed, but less obviously so. 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.


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'm a recovering IOC addict. I'm finding it hard to justify using IOC for DI in most cases these days. IOC containers sacrifice compile time checking and supposedly in return give you "easy" setup, complex lifetime management and on the fly discovering of dependencies at run time. I find the loss of compile time checking and resulting run time magic/exceptions, is not worth the bells and whistles in the vast majority of cases. In large enterprise applications they can make it very difficult to follow what is going on.

I don't buy the centralization argument because you can centralize static setup very easily as well by using an abstract factory for your application and religiously deferring object creation to the abstract factory i.e. do proper DI.

Why not do static magic-free DI like this:

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();
        }
    }
}

Your container configuration is your abstract factory implementation, your registrations are implementations of abstract members. If you need a new singleton dependency, just add another abstract property to the abstract factory. If you need a transient dependency, just add another method and inject it as a Func<>.

Advantages:

  • All setup and object creation configuration is centralized .
  • Configuration is just code
  • Compile time checking makes it easy to maintain as you cannot forget to update your registrations.
  • No run-time reflection magic

I recommend sceptics to give it a go next green field project and honestly ask yourself at which point you need the container. It's easy to factor in an IOC container later on as you're just replacing a factory implementation with a IOC Container configuration module.


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.


I'm with you, Vadim. IoC containers take a simple, elegant, and useful concept, and make it something you have to study for two days with a 200-page manual.

I personally am perplexed at how the IoC community took a beautiful, elegant article by Martin Fowler and turned it into a bunch of complex frameworks typically with 200-300 page manuals.

I try not to be judgemental (HAHA!), but I think that people who use IoC containers are (A) very smart and (B) lacking in empathy for people who aren't as smart as they are. Everything makes perfect sense to them, so they have trouble understanding that many ordinary programmers will find the concepts confusing. It's the curse of knowledge. The people who understand IoC containers have trouble believing that there are people who don't understand it.

The most valuable benefit of using an IoC container is that you can have a configuration switch in one place which lets you change between, say, test mode and production mode. For example, suppose you have two versions of your database access classes... one version which logged aggressively and did a lot of validation, which you used during development, and another version without logging or validation that was screamingly fast for production. It is nice to be able to switch between them in one place. On the other hand, this is a fairly trivial problem easily handled in a simpler way without the complexity of IoC containers.

I believe that if you use IoC containers, your code becomes, frankly, a lot harder to read. The number of places you have to look at to figure out what the code is trying to do goes up by at least one. And somewhere in heaven an angel cries out.


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. Nothing else. 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. We'll see. 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.


Using a container is mostly about changing from an imperative/scripted style of initialization and configuration to a declarative one. This may have a few different beneficial effects:

  • Reducing hairball main-program startup routines.
  • Enabling fairly deep deployment-time reconfiguration capabilities.
  • Making dependency-injectable style the path of least resistance for new work.

Of course, there may be difficulties:

  • Code that requires complex startup/shutdown/lifecycle management may not be easily adapted to a container.
  • You will probably have to navigate any personal, process and team culture issues -- but then, that's why you asked...
  • Some of the toolkits are fast becoming heavyweight themselves, encouraging the sort of deep dependency that many DI containers started off as a backlash against.

I'm a fan of declarative programming (look at how many SQL questions I answer), but the IoC containers I've looked at seem too arcane for their own good.

...or perhaps the developers of IoC containers are incapable of writing clear documentation.

...or else both are true to one degree or another.

I don't think the concept of an IoC container is bad. But the implementation has to be both powerful (that is, flexible) enough to be useful in a wide variety of applications, yet simple and easily understood.

It's probably six of one and half a dozen of the other. A real application (not a toy or demo) is bound to be complex, accounting for many corner cases and exceptions-to-the-rules. Either you encapsulate that complexity in imperative code, or else in declarative code. But you have to represent it somewhere.


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.


The solution was to call AddSingleton with my class being instantiated in the method parameter in my Startup class:

services.AddSingleton(s => new FunClass(new MyContext(null, Configuration["Data:DefaultConnection:ConnectionString"])));

The solution was to change my DbContext class:

public class MyContext : IdentityDbContext<ApplicationUser>
{
    private string connectionString;

    public MyContext()
    {

    }

    public MyContext(DbContextOptions options, string connectionString)
    {
        this.connectionString = connectionString;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // Used when instantiating db context outside IoC 
        if (connectionString != null)
        {
            var config = connectionString;
            optionsBuilder.UseSqlServer(config);
        }

        base.OnConfiguring(optionsBuilder);
    }

}

As multiple people have however warned, using a DbContext in a singleton class might be a very bad idea. My usage is very limited in the real code (not the example FunClass), but I think if you are doing this it would be better to find other ways.





dependency-injection inversion-of-control ioc-container