Tuesday, May 1, 2012

Unity, Injection and the surprise InvalidCastException of System.Type

Chances are if you have run into this message you might be trying to inject your constructor, property or method with a type as a type. The reason? Default behavior of unity is to resolve a type to an instance and inject it for you. This feature applies to all injection and is not terribly clear in the Unity documentation. It also comes up quite frequently on the stackoverflow unity channel.
An example of the full error message in all it's glory:
Resolution of the dependency failed, type = \"MyNamespace.IMyInteface\", name = \"(none)\".\r\nException occurred while: 
Resolving parameter \"myConstructorParameter\" of constructor MyNamespace.MyClass.Logger(System.Type myConstructorParameter).
Exception is: InvalidCastException - Unable to cast object of type 'MyActualInstanceOfTypeProvidedToConstructor' to type 'System.Type'.
At the time of the exception, the container was:

Resolving MyNamespace.MyClass,(none) (mapped from MyNamespace.IMyInterface, (none))\r\n  Resolving parameter \"myConstructorParameter\" of constructor MyClass(System.Type myConstructorParameter)
Solving this issue is not as complicated as the error message may seem... for unity. Microsoft did left some flexibility for us, it simply involves wrapping the type argument as an injection parameter:
new ParameterOverride("typeParameterArgument",new InjectionParameter(typeof(Type),typeof(MyNamespace.MyClassUsedAsInjectedTypeArgument)))
Why? if you dive into the reflection tool of your choice you will eventually come across "InjectionParameterValue.ToParameter" this little gem will show you that unity is checking to see of the value is an InjectionParameterValue if it is no and the value is a type return a new ResolveParameter using the argument as a type.