Introduction
Whenever I start a new “pet” project I usually *want* to use IoC, but I don’t really want the hassle of taking a dependency on a container, or adding another binary to my project. Usually this leaves me using “poor man’s IoC”, whereby I define dependencies in my constructors, but I pass them in manually or construct them using constructor chaining.
I’ve thought for some time that it would be useful to put together a container that fits the bill for that scenario, but also attempts to “lower the barrier of entry” for developers that are new to IoC, and may be scared off by the “big boys”. A couple of weeks ago @DotNetWill posted his simplified container, and that gave me the kick up the backside I needed to create my own
Introducing TinyIoC
Now you might ask “do we really need *another* IoC container?” – and it’s a reasonable question. We already have Unity, Ninject, StructureMap, AutoFac.. the list goes on. TinyIoC makes no attempt to go “head to head” with any of these other containers, instead TinyIoC has been designed to fulfil a single key requirement:
To lower the “level of entry” for using an IoC container; both for small projects, and developers who are new to IoC.
To that end, TinyIoC attempts to stick the following core principals:
- Simplified Inclusion. No assembly to reference, no binary to worry about, just a single cs file you can include in your project and you’re good to go. It also works on Mono, and on MonoTouch for the iPhone / iPad.
- Simplified Setup. With auto-resolving of concrete types and an “auto registration” option for interfaces, setup is a piece of cake. It can be reduced to 0 lines for concrete types, or 1 line if you have any interface dependencies.
- Simple, “Fluent” API. Just because it’s Tiny, doesn’t mean it has no features. A simple “fluent” API gives you access to the more advanced features, like specifying singleton/multi-instance, strong or weak references or forcing a particular constructor.
The following snippet gives an example of the simplified setup:
// TinyIoC provides a lazyily constructed singleton // version of itself if you want to use it. var container = TinyIoCContainer.Current; // By default we can resolve concrete types without // registration var instance = container.Resolve<MyConcreteType>(); // We can automatically register all concrete types // and interfaces with a single call. container.AutoRegister(); var implementation = container.Resolve<IMyInterface>();
So Where Now?
If you want to grab the source, read the tests, or take a look at some more complex examples of the API, wander on over to the homepage on bitbucket. I’m happy to take comments and suggestions – just grab me on Twitter or ping me an email from the contact form.
Over the next few weeks I will be posting a series of “beginners” articles on the hows and whys of IoC. I will be using TinyIoC specifically, but the majority of concepts and content can equally apply to other containers. I may even do a “File, New” screencast to show how “un-scary” this stuff is, and how it doesn’t really add any extra development effort,

What happens if there are multiple implementations of IMyInterface in the AutoRegister example?
“Last one wins” in that scenario. I did consider throwing an exception, or even adding named registrations, but thought both of those would be significantly less friendly.
In my mind, if you hit this issue you can either:
a. Get rid of autoregistration and switch to a more “standard” manual approach.
or, my preferred option:
b. Auto-register to get the vast majority of registrations done, then manually register your exceptions:
container.AutoRegister();
container.Register();
container.Register("OtherOne");
What about container.AutoRegister(DuplicateOption.ThrowException) / AutoRegister(DuplicateOption.Ignore)?
I think I’d like to keep the default to be “ignoring” duplicates, but it’s a nice idea to add an option for it – either that or return a boolean for whether any issues were found, then it’s up to you whether you do anything about it or not?
I’ll also add support for abstract base classes too, in the same way that interfaces get added.
How about make it even more configurable:
container.AutoRegister().AmbiguousResolutionBehaviour(types => types.First())
container.AutoRegister().AmbiguousResolutionBehaviour(types => throw new AmbiguousResolutionException(types))
container.AutoRegister().AmbiguousResolutionBehaviour(MyCustomMethodForResolvingWhichOneIWant)
I’ve changed AutoRegister so you can now get it to throw a meaningful exception if there’s duplicates. The exception message shows the interface/base class that has the clash, and also a comma separated list of all the potential implementations.
I could take that IEnumerable and pass it into a user specified delegate, but I’m not sure whether that’s taking AutoRegister too far or not – if there’s definite logic you need in your registrations, or if you need named registrations etc., then you might be best either switching to just Register, or mixing AutoRegister with some specific Register commands afterwards?
It all looks pretty sweet and I love some of the ideas. Great work!
Really enjoying your posts recently Steve. Read half the code last night of TinyIoC and for it looks great. Didn’t understand why you’d put in all in one .cs until this post. Looking forward to the series.
Like it. You can keep it up to date with this http://www.adverseconditionals.com/2010/01/easy-peasy-web-dependencies-using-t4.html
It’d be pretty cool if, when faced with multiple implementations, it picked up the one in the launch assembly first. This way you can have a default implementation of a service in a common library, but override it in your different applications.
Thanks for the comment, that T4 thing is pretty cool
You can mix and match AutoRegister and Register, and even AutoRegister more than one assembly, so you could AutoRegister your common library first, then do it against your app assembly to copy over any customisations you have in there.