Unity type resolution in HelloWorld Quickstart using reflection?

Topics: Prism v1, Prism v2 - Silverlight 2, Prism v2 - Silverlight 3, Prism v2 - Silverlight 4, Prism v2 - WPF 3.5, Prism v2 - WPF 4, Prism v4 - Silverlight 4, Prism v4 - WPF 4
Oct 7, 2010 at 7:55 PM
Edited Oct 7, 2010 at 7:59 PM

This is a Unity-Dependency-Injection question about the HelloWorld.Silverlight Quickstart.  The sample's Bootstrapper class has a CreateShell() method that makes the following call:

    return Container.Resolve<Shell>();

This is asking the Unity DI-container to somehow construct an instance of the type Shell.  Since we never explicitly register the type Shell with Unity, how does it know how to build one?

Apparently it uses reflection against the entire current assembly (or maybe AppDomain?) looking for a type by that name?  Is that true?  (The Shell type does live in the same main assembly as the Bootstrapper class which is making this Resolve call.)

Putting a breakpoint in the constructor of Shell shows the following call-stack.  The "DynamicMethod" part is presumably reflection.  True?

Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(...)
Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(...)
Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(...)
Microsoft.Practices.Unity.UnityContainer.DoBuildUp(...)
Microsoft.Practices.Unity.UnityContainer.DoBuildUp(...)
Microsoft.Practices.Unity.UnityContainer.Resolve(...)
Microsoft.Practices.Unity.UnityContainerExtensions.Resolve<HelloWorld.Shell>(...)
HelloWorld.Bootstrapper.CreateShell()

Thanks,
SLEverywhere

Oct 7, 2010 at 8:30 PM

Unity has a great feature where even if they are not registered, you can request an instance of a concrete type and Unity will figure out how to create it and give you an instance. I believe Unity looks in the AppDomain for concrete types...but it has been a while since I looked at that.  At a high level, this is what is happening :

  • You request that Unity creates an instance of a type for you using Resolve.
  • Unity finds the concrete type (in the AppDomain) and determines which constructor to use to create the type using reflection.
  • Unity dynamically generates a factory method to create the concrete type, and uses emit to compile and create a runnable instance of the factory method.  This may chain calls to other factory methods for other types if there are dependencies that need to be injected.
  • Unity then calls the emitted factory method, returning the instance and caching the factory method for later use.
  • Later calls to Resolve the same type use the cached and emitted factory method, with no further reflecion "hit"

For types that are registered, the path is similar, but there are a few differences before the factory method is emitted. For more detailed information on how this works, I would recommend going to the Unity discussions (http://unity.codeplex.com/discussions). Or just trust that it does work. :-)

For simple cases, in the CreateShell method, you can use "new" rather than resolving the instance.  However, if you want to use DI on the shell and have either properties or constructor arguments automagically inserted for you, you should use Resolve. We used Resolve in the samples as a starting point that will not require changes later for people need DI on their shell types.

Does that help clear up the confusion?

Oct 7, 2010 at 9:07 PM
Edited Oct 7, 2010 at 9:07 PM

>Does that help clear up the confusion?

Yes Michael, thanks for the detailed explanation.

I am just learning Prism in detail and for me Dependency-Injection is the most unfamiliar and "magical" part.  Looking behind the "magic curtain" a little helps inspire more confidence.

Thanks,
SLEverywhere