views:

154

answers:

7

I would like to try using an DI/IoC framework for the first time in a small-ish but growing project, and I don't want to disturb the project much by introducing bulky dependencies. The project itself is partly intended to be used as a library in other projects, and I don't want to trouble users with managing extra dependencies. It's also a matter of taste--I feel the size of a component should be proportional to the amount of services that I actually need. I hate to incorporate a bulky component with dependencies of its own, only to use a small part of it.

So, for .NET, is there a small DI/IoC framework that compiles to a single DLL with no dependencies other than standard libraries, that (if necessary) could be directly embedded in the assembly that uses it, and that emphasizes code-based/fluent (as opposed to XML) wiring? It must not require .NET framework 4.0.

+3  A: 

Take a look at Ninject.

Jordão
The .NET Framework 3.5 download at http://ninject.org/download contains 6 DLLs exceeding half a meg, heavier than I was hoping for.
Qwertie
All you reference in your project is the single Ninject.dll assembly which does meet your lightweight criteria. There is an Extensions and Web.Mvc set of assemblies that is additive to the base NInject functionality if you need it.
Dave White
Are those assemblies optional, or does Ninject.dll require them? Is the XML file required?
Qwertie
Optional, xml not required. Ninject is light and non-intrusive.
qstarin
Yes, all the other assemblies are optional.
Jordão
Ah, good. Ninject.dll itself is just 94 KB which I am comfortable with.
Qwertie
Accepted - the design principles at http://wiki.github.com/ninject/ninject/ are very attractive and I am a sucker for the slick website.
Qwertie
Unaccepted - the documentation is in a messy state (and looking at the source code doesn't help without knowing the concepts... I'm lost in a web of "bindings", "components", "kernels", "planners" and "settings"). Moreover...
Qwertie
... Moreover, it is SLOW. Given an empty "INothing" interface, a "Nothing" class, and a trivial binding, a tight loop that calls kernel.Get<INothing>() can produce only 36,000 objects per second in my Release build. In contrast, just calling "globalVariable = new Nothing()" produces 105,000,000 objects per second (about 3,000 times faster). They may use Lightweight Codegen for the actual constructor call, but the constructor call overhead is dwarfed by so many checks, LINQ queries, layers of abstraction, method calls, and temporary objects Ninject makes.
Qwertie
+4  A: 

I feel much the same as you do about IOC frameworks. I use IOC all the time, I just don't see the need for a Framework much.

Having said that, the one I'd use if I were to pick one up would be AutoFac

It's simple, easy to grasp, and feels lightweight.

CubanX
http://nblumhardt.com/2010/04/introducing-autofac-2-1-rtw/ - says "Autofac uses the underlying support in .NET 4.0"
Qwertie
Right, AutoFac 2.1 does. But the versions before that (1.4) don't need 4.0. If you're deploying a 4.0 app, then the fact it uses the underlying .Net stuff is a good thing :)
CubanX
I am restricted to VS 2008 and besides, don't want to require users to upgrade their .NET Framwork. It seems there is a .NET 3.5 version of AutoFac 2.2 but it comes with 5 DLLs and a XML file bigger than the 5 DLLs combined, I wonder how much of that is required?
Qwertie
I just noticed, both Ninject and AutoFac have XML files that are much larger than their main DLL.... Edit: haha! I see, the XML files just contain documentation. So they are not actually required at runtime, good news.
Qwertie
You only need Autofac.dll, and it totally works with .Net 3.5
Peter Lillevold
+2  A: 

I'd also suggest in addition to NInject that you look at Microsoft's DI Framework, Unity.

Dave White
A: 

Try StructureMap.

The core StructureMap.dll is pretty small.

Jordão
A: 

I work with a rather large system and we've manually injected everything. We make use of the abstract factory pattern to tidy up most of the injection/wiring and it's worked out fine.

DI Frameworks are plentiful. Before taking on an extra external dependency, take some time to consider if applying a different/new pattern would solve your problems.

edit: (possibly biased/unjust) Reasons I haven't used a DI framework:

  • If you use a DI framework, you have to ship the DI framework with your software. This can be a show stopper for some, and others might have to argue the merits of the extra dependency.
  • You still have to build constructors to take dependencies
  • And you still have to tell (or at least hint) at the DI framework what to use. The only major difference is your using the DI factory rather than your own.

As for building that factory, most refactoring tools can do 90% of the work for you with very few keystrokes.

Josh Sterling
Have you actually used a DI framework? If so, did you find it was more trouble than it was worth?
Qwertie
I fail to see how manual injection in a large system is **less work** than having it done automatically using a DI framework.
Peter Lillevold
Response was a bit long for a comment, edited my answer instead.
Josh Sterling
+3  A: 

Any framework that you will introduce will eventually become a dependency of your app. Also, people have varied definitions of what lightweight is. Take a look at Unity, or StructureMap or Castle Windsor as they tend to be more popular. Scott Hanselman has a whole list, here. Take your pick.

Roma
+1 for the list. Technically if I embed the IoC container in one of my DLLs and change the namespace, it won't look like a dependency from the outside, plus I'd get the option of deleting anything I don't use. Given how they explain its design, I'm thinking (Windsor) MicroKernel is amenable to that approach...
Qwertie
@Qwertie at the bottom of the referenced Hanselman post is a link to two IoC containers in 15 lines of codes. Their purpose is to be extremely lightweight when you don't need a "framework." Perhaps it's worth looking into.
Ben McCormack
A: 

There are examples on the web about writing your own container, although they are very basic and would lack features provided by a more robust framework.

Matt