In simple terms and/or in high-level pseudo-code, how does a DI container work and how is it used?
At its core a DI Container creates objects based on mappings between interfaces and concrete types.
This will allow you to request an abstract type from the container:
IFoo f = container.Resolve<IFoo>();
This requires that you have previously configured the container to map from IFoo
to a concrete class that implements IFoo
(for example Foo
).
This in itself would not be particularly impressive, but DI Containers do more:
They use Auto-Wiring which means that they can automatically figure out that if IFoo
maps to Foo
and IBar
maps to Bar
, but Foo
has a dependency on IBar
, it will create a Foo instance with a Bar when you request IFoo
.
They manage the lifetime of components. You many want a new instance of Foo
every time, but in other cases you might want the same instance. You may even want new instances of Foo
every time, but the injected Bar
should remain the same instance.
Once you start trying to manually manage composition and lifetimes you should start appreciating the services provided by a DI Container :)
Many DI Containers can do much more than the above, but those are the core services. Most containers offer options for configuring via either code or XML.
When it comes to proper usage of containers, Krzysztof Kozmic just published a good overview.