I don’t like the Unity Inversion of Control framework. I find it too verbose, requiring user to be too explicit (except for cases where it doesn’t while it should), not intuitive and I generally don’t like its design. Unfortunately, it’s the only IoC framework I’m allowed to used at work, so I’m stuck with it, good or bad. There are times however that I’m just astonished by how it works, and mostly, in a negative sense. There’s an important principle in computer science, called Principle of the Least Surprise, that says, that framework (in particular) should have its API designed in such a way that it works like the user (programmer in this case) would expect it to.
Let’s take… well, I don’t know… Unity for example.
Take a look at the following piece of code:
Everything seems pretty obvious here, to anyone who has ever used an IoC container. Using generic parameter I register a type (ServiceHost) service, with specific key (myService), then I explicitly (I could write a whole post about how not good idea it is, but it’s leave it out for now) specify constructor I want used and it’s parameters using InjectionConstructor, next I specify method injection with InjectionMethod class. Pretty simple, huh?
Now, let’s take a closer look at InjectionMethod constructor. It takes a string, denoting method’s name, and next it takes the list of objects (array of System.Object to be precise) that should be used as method’s parameters, right? the tooltip leaves no doubt about it. It says:
methodParameters: Parameter values for the method.
Well, if you think it’s obvious imagine my surprise when I saw this, after running this code:
Turns out it’s not so obvious to everybody. To make the long story short, pulling Unity’s source code showed, that there’s a fine print to that method (well, actually there’s none, it just works in unexpected ways, maybe that behavior is mentioned somewhere in the docs, but I’m paid for writing working code, not for reading docs). It does use the parameters you provide literally, most of the time. However if you pass an argument of type System.Type, like I did, Unity implicitly tries to know better, what you want to do, than yourself. It assumes that since you passed a System.Type, as System.Object parameter, for sure what you meant was not to use it literally, but instead to use instance of service of that type registered with the container, and that’s what it tries to do. It then fails to bind those parameters to the method, which results in aforementioned exception. To make it work you have to be yet smarter and know another implicit rule of Unity, that if you pass as parameters values of types derived from InjectionParameterValue it will handle them correctly. So changing the above code to this, yields the expected results: