I’m just now beginning to experiment with IoC containers. Currently, I’m using a home-grown factory to build my ViewModels, which come in two flavors: singleton, and id-based. In other words, my application (by definition) only has one Room at a time, and hence only one RoomViewModel, but many users can be in that room, so I need many UserViewModels. But I want to make sure that, say, for the User with UserId=”johnsmith”, only one UserViewModel is ever created, and any attempt to retrieve that UserViewModel will return the same instance.
I don’t know if it will help explain things or confuse them, but this is the method that I’m currently using to do this:
public ViewModelType GetViewModelByKey<ViewModelType, KeyType>(KeyType key)
where ViewModelType : AlantaViewModelBase, new()
{
IDictionary dictionary;
var type = typeof(ViewModelType);
if (!keyedViewModelDictionaries.TryGetValue(type, out dictionary))
{
dictionary = new Dictionary<KeyType, ViewModelType>();
keyedViewModelDictionaries.Add(type, dictionary);
}
var viewModels = (Dictionary<KeyType, ViewModelType>)dictionary;
ViewModelType vm;
if (!viewModels.TryGetValue(key, out vm))
{
vm = new ViewModelType();
viewModels.Add(key, vm);
vm.Initialize(this);
}
return vm;
}
This means that these two calls will return separate instances:
// Get VM for user.UserId="john";
var userVM1 = viewModelFactory.GetViewModelByKey<UserViewModel, string>("john");
// Get VM for user.UserId="suzie";
var userVM2 = viewModelFactory.GetViewModelByKey<UserViewModel, string>("suzie");
But these will return the same instance:
// Get the same VM for user.UserId="bob";
var userVM1 = viewModelFactory.GetViewModelByKey<UserViewModel, string>("bob");
var userVM2 = viewModelFactory.GetViewModelByKey<UserViewModel, string>("bob");
The ability to do this solves a heck of a lot of data-binding and synchronization problems, so it’s not a pattern that I’m going to give up on easily.
But I’d like, if possible, to move to a standard IoC container, since presumably they have more features, don’t require specific types, and are certainly more standardized. But in reading up on them, I haven’t come across any obvious indication that they support my second sort of approach. In other words, they all support the standard two lifestyles (singleton and transient), but I want something a little different: singleton per object identity. Do the standard IoC containers support this? How? Which ones?
Sorry if this is a basic question.
MEF supports this via Export using a “Contract Name”. This allows you to export and import with contract names specified:
Edited by Ken Smith
See the discussion below for our eventual conclusion that the IoC containers don’t support this sort of behavior out of the box, and perhaps aren’t really designed to solve this problem.