Injecting specific model instances for various controls

Dec 31, 2008 at 1:42 PM
We're new to Unity and having some trouble figuring out the best way to approach this - but I'm sure it's something that's been done before.

We understand how to inject services, like logging. But as we get further down the control/screen tree, our dependencies are on specific model instances and not just on services. (This is a win app, by the way.)

Imagine a shell that connects to a database and gets a list of people - it's injected with some sort of DB service. No problem. Now we click on several names, loading each person into a new tab in our TabControl. We have a PersonView and PersonViewModel that will handle the display of each individual instance of Person, our model class.

I want to make Person a dependency, and have Unity inject it when I call container.Resolve<PersonView>. But I need individual, specific instances of Person, not a Person generically instantiated by unity with the default constructor. How do I get a specific Person into my PersonView?

My thinking right now is that I want child containers, one for each tab, which would be one for each person. So when a tab is created, it has a corresponding container which registers an instance of Person. Now I can resolve any view that needs a Person using that child container, and it will resolve the instance - and anything it needs from the parent container, like a logging server registered with the parent.

Now I could open a dialog for the shipping address, creating another child container which registers that specific instance of Address. Views resolved in the context of this new container can have dependencies on Address, Person, and Logging, each of which comes from a different container in the heirarchy.

Am I on the right track here? If so, any advice on how to create child containers "on the fly" - like when a person is clicked and a tab is created - would be greatly appreciated. If not, can anyone point me to a Unity example that does more than create single window with a reference to some generic service? That's the classic example; I can't find anything about child view/viewmodel/presenters that are created in response to user interaction.

Sorry for the long post.... 
Jan 5, 2009 at 6:08 AM
You can resolve a type from a container without using the default constructor by using the InjectionConstructor.  For example,

public class Student: IPerson
{
    public Student()
    {
    }
    
    public Student(string name, int age)
    {
         .....
    }
}

IUnityContainer container = new UnityContainer();
container.RegisterType<IPerson, Student>(new InjectionConstructor("Student1", 20);
Student student = container.Resolve<Student>();

The student variable here will be instantiated using the constructor with 2 parameters(name and age).

If this is not what you're looking for, I'm not sure creating child containers is the best approach.  If you're creating a specific container, why not just create the specific person? Anyway, here's the code on how to create a child container.

IUnityContainer parentCtr = new UnityContainer();
IUnityContainer childCtr = parentCtr.CreateChildContainer();

Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com


Jan 19, 2009 at 1:57 PM
I'm not sure if Sarah answered your question, but here's what we've done.

Within our application we have a shell which can open up any number of child views within a tab (similar to what you've described, I think).  When we open a new view we resolve a presenter (we chose to resolve the presenter instead of the view because it felt more natural).  We then take the view (which is a dependency of the presenter) and push it into the shell.  We also explicitly push our model into the presenter (through a property set) instead of using a constructor parameter.  I like this better because using the container to fulfill the model dependency felt somewhat unnnatural. 

Now, if Unity supported passing dependency objects through a Resolve() call, it might be possible, but I don't think I like using the "new InjectionConstructor()" method.  For one, I think it might not be thread safe. 
Mar 18, 2009 at 11:08 PM
Hi,

Thanks for the feedback, both of you. Just to follow up:

We went, in some cases, with the child container idea. We're registering specific instances of each child object in the child containers and then resolving the views (and the view models that are required to construct them.)

But as I read more about Unity, I came to the conclusion that business objects aren't really what it was intended to inject. They aren't mockable for testing - maybe the IGetDataFromSomewhere interface is mockable, but not the Person class. And they aren't a globally available service, like a data service or a web service or a logging service, etcetra. They're a thing.

I've come around to Jeremy's way of thinking, translated to MVVM of course.

So, take the case of showing multiple business objects in a similar context, like showing multiple Person objects on different tabs. My current thinking is that I would use unity to resolve the PersonViewModel with any services it needs, like logging or a data layer service. Then I would simply assign the correct Person instance to the ViewModel without using unity at all. Then stick it in the View and show the view.

I also think it would be nice to have a Resolve() overload that allowed me to pass specific objects in. Maybe something like container.Resolve<PersonView>(new object[] {myPerson}). This might cause any dependency on type Person to resolve to the supplied person.