6

I am looking for a really simple and lightweight IoC Container whose C# source can be included in my own project (thus not making an external reference).

The reason for this is that I am writing an infrastructure and would like to provide a single .dll file, without any additional dependencies.

I also do not want to ILMerge my assembly with the IoC assembly..

I thought about MEF, some other suggestions?

tshepang
  • 12,111
  • 21
  • 91
  • 136
dux2
  • 1,770
  • 1
  • 21
  • 27
  • You might want to tag this .net for more suggestions. – Mike Gardiner Jan 23 '12 at 08:32
  • 1
    look at this question: http://stackoverflow.com/questions/2515124/whats-the-simplest-ioc-container-for-c there is an online example – Felice Pollano Jan 23 '12 at 08:41
  • 6
    If you are writing a library, you shouldn't have to use a DI Container at all: http://stackoverflow.com/questions/2045904/dependency-inject-di-friendly-library/2047657#2047657 – Mark Seemann Jan 23 '12 at 08:59

4 Answers4

3

If you're using .NET 4.0 you have MEF included.

For .NET 2 I once wrote something similar using interfaces and Reflection. There are a lot of tutorials out there describing that process. Even if you can use MEF, its still worth attempting some reflection tutorials as this is how MEF works underneath.

Also check out this question which has some good answers. TinyIoC looks like its just a single source file.

Community
  • 1
  • 1
Tim
  • 7,746
  • 3
  • 49
  • 83
3

If you don't need anything fancy, a DI container can be really short:

public class Container
{
   private readonly Dictionary<Type,Func<Container,object>> factories;
   private readonly Dictionary<Type,object> cache;

   public Container()
   {
       this.factories = new Dictionary<Type,Func<Container,object>>();
       this.cache = new Dictionary<Type,object>();
   }

   public void Register<TContract>(Func<Container,TContract> factory)
   {
       // wrap in lambda which returns object instead of TContract
       factories[typeof(TContract)] = c => factory(c);
   }

   public TContract Get<TContract>()
   {
       var contract = typeof(TContract);
       if (!cache.ContainsKey(contract))
       {
           this.cache[contract] = this.factories[contract](this);
       }
       return (TContract)this.cache[contract];
   }
}

Which you would use like this:

var container = new Container();
container.Register<ICar>(c => new Car(
    c.Get<IEngine>(), c.Get<IWheel>()));
container.Register<IWheel>(c => new Wheel());
container.Register<IEngine>(c => new Engine());

var car = container.Get<ICar>();

Even more minimalistic would be to do dependency injection without a container:

IWheel wheel = new Wheel();
IEngine engine = new Engine();
ICar car = new Car(engine, wheel);

However, for complex object graphs it can quickly get complicated to maintain the correct construction order during refactorings. The container doesn't have this problem.

Wim Coenen
  • 66,094
  • 13
  • 157
  • 251
0

I very much like Castle.Windsor which is open source, so you could add the relevant code files to your project

Andrew Skirrow
  • 3,402
  • 18
  • 41
  • 2
    Windsor is not my definition of a lightweight container. It includes about 4 assemblies and a lot of source files / classes. – dux2 Jan 23 '12 at 08:40
0

It's not really that difficult to roll your own container, depending on the type of features you need. It is however very easy to create leaks when doing so, so I guess that you would probably want to use a tested-and-tried solution.

MEF is used by some as a container but (notable) others say that MEF is not an IOC container, in essence MEF was designed to be a plugin architecture not a dependency injection container.

Considering all this, I would recommend you either embed the full source code for the container of your choice in your application or use a tool to merge it's assembly into your own. ILMerge is a tool that could do that, most commercial obfuscators can help you do this as well. If you're building a commercial library or application I would definitely recommend using a proper obfuscator anyway.

Community
  • 1
  • 1
Marnix van Valen
  • 13,265
  • 4
  • 47
  • 74
  • As I stated in my question, I am willing to embed the container's source code in my own project, but I am looking for a tested container with a minimum number of files and classes. No ILMerge please. – dux2 Jan 23 '12 at 08:52
  • What are the requirements for the container? What kind of life cycle support do you need? Do you want XML config, a fluent configuration API or are you happy configuring each type explicitly? – Marnix van Valen Jan 23 '12 at 08:56
  • I would like to configure the container by code. Would like support for singleton and transient life cycles. – dux2 Jan 23 '12 at 09:17
  • 1
    You may find [this blog post](http://ayende.com/blog/2886/building-an-ioc-container-in-15-lines-of-code) interesting. It demonstrates an ultra lightweight container. It supports only transient lifestyle but adding support for singletons should be easy. Is that what you had in mind? – Marnix van Valen Jan 23 '12 at 09:36
  • Thanks. I will check it out. I also found this one: http://stackoverflow.com/a/2598839/978164 which looks interesting. – dux2 Jan 23 '12 at 09:49
  • Nice, that looks more complete than Ayende's blog post. – Marnix van Valen Jan 23 '12 at 10:00