I understand the benefits of injecting dependencies into objects, but have not found much guidance on the types of objects to inject and when to make them singletons.

If we take as as example an application with the following types of objects:

Services (including repositories and business services such as calculateprice)

Views

ViewModels

Services

Injecting services is the typical example given and it is clear these are not registered as singletons in the container as they are statelesss.

Was it the original intention that only services should be injected by containers?

Views/ViewModels & other stateful long lasting objects

The general way to access a long lasting object in several places has been to use a registry (or similar), assuming we cannot pass it around as a parameter. Now we have the option to register the object as a singleton in a container and inject it where needed.

I can't see any problem using the singleton in a container approach beyond the issue of removing the object from the container when its lifecycle ends (not sure how easy that is going to be - I use Unity).

Would be interested to hear of any problems others can forsee.

As an interesting aside, the MVVM Light framework uses a ViewModelLocator rather than injecting viewmodels.

3 Answers
3

Well, it depends on what you need. If you'll never ever have two or more views of the same type, then I guess it's ok to register them as singletons.

But then, what if you have a view composed of two other views (and their view models), for instance, if you are comparing some data? You'll can't use the same instance, since you need to populate those with different data.

Also if you have many views, and some type of navigation, where each view gets created when you get to it, then those singleton views would linger on somewhere when you navigate away from them. The container would be keeping a reference, and they would never get collected.

EDIT: With regard to your comment, I think you wouldn't have any issues if you registered the view as a singleton. Having said that, I wouldn't do it. I usually use "singletons" for stateless (or statefull, but where the state can't be changed after it's set when instantiated the first time) objects like repositories, or objects that absolutely have to be single instances during the whole application lifetime. In MVVM that would be some controller which is responsible for managing views (for navigation). I'd leave the views themselves, and their view models as normal objects, even if at first I'll be using just one of them. This is just my preference, though.

PS: I don't have experience with MVVM Light, but using the container as a service locator is generally considered an anti-pattern by many, as you are introducing a dependency to the container. Your views and view models (and domain models) should be as free as possible of the "infrastructure" constructs such as the container. When your code gets to the view model, it should just have all that it needs, and not look for it using the container.

thanks, yes if a view can be duplicated, then would not make it (+ related VMs) singleton and would probably use a registry if references to these were required later on. Regarding views that we can navigate away from and forget, then those would also not be singletons. The question was rather where the design implies a single view, then are there any issues you can foresee in making them singletons in a container.
–
sturdytreeFeb 3 '13 at 21:42

Well, the only issue I can think of is that it later turns out that you need a second instance of the same view. Check the edit too, it seemed too big for a comment.
–
PinetreeFeb 3 '13 at 22:36

thanks again, it's a question of alternatives, and if you wouldn't use a singleton in a container for views and vms, then I can only imagine you would end up with a registry, which seems essentially the same as a service locator?
–
sturdytreeFeb 3 '13 at 22:54

The controller uses the container to create the views with their viewmodels, so yes, I do use some kind of service location. But it's contained to the controller only, and the views themselves are not looking for their viewmodels, they have them injected. And you could argue that the controller itself serves as kind of a registry for the views. But this is just for the navigation history. As soon as you go back, the current view gets disposed. When you navigate to that view again, a new instance gets created.
–
PinetreeFeb 4 '13 at 9:43

This problem really comes down to the intended lifecycle/scope of your instances.

Is there going to be a single instance of your class for the duration of the application? Then a "singleton" is fine. I've quoted singleton because it's really the application scope it's referring to.

A good overview of how scopes are nested and dependency injection works with that, see the PicoContainer introduction (I'm not suggesting you use PicoContainer, just read the intro to get a grip on this stuff).

I would add that our Vaadin views maintain state on the server, chiefly the controls that form them. If your views are in a similar situation in a multi-user environment, you can't use singletons. You could use something close, like a Prototype, to carve out new instances out of a template. You could reuse views for the same user for different iterations of the same workflow, for which you'd probably employ Flyweight, or else you'll need to reset the view state at the beginning of each reuse, which is probably not worth it.

In any case, hiding the detail behind a registry will give you the option to switch between the two models if you find issues down the road.

thanks for your response. In a multi-user desktop scenario, each user would run the application on their own system and so the view could still be a singleton? In a web context, I'm not that experienced, but imagine you could still have a singleton if each user is given their own process on the server.
–
sturdytreeFeb 4 '13 at 8:58

Yes, in your case, the view can be a singleton, barring multiple stateful views opened by the same user on her desktop. But beware view reuse, as reinitializing views just to recycle singletons can get messy. Either way, don't let your view consumers (controllers and what have you) know that they are singletons. Best to hide that detail behind a registry or a factory. Focus closely on what the view must promise about its lifecycle (e.g., that there's only one at any given time, e.g. due to statefulness, multiple users) and that pretty much tells you if it can be a singleton.
–
Mihai DanilaFeb 4 '13 at 18:42