I have set up a MVVM application with Autofac and MEF to solve the problem you are talking about. To make a long story short, I have created a service interface IViewModelProvider
which serves ViewModels for arbitrary models. The implementation of this service provides a cache for all ViewModels and creates ViewModels for models if no ViewModels of the requested ViewModel type for a particular model can be found.
The ViewModelProvider
is kind of it's own IoC container, which reflects all loaded assemblies at initialization and then resolves the dependencies at runtime. The ViewModelProvider registers an instance of itself for the service IViewModelProvider
and thus can pass itself to the ViewModels
which require the ability to instantiate new ViewModels.
I am very happy with this solution, as I feel like having a neat separation of concerns here. The global ViewModel cache is awesome, because it saves resources and you can actually compare ViewModels for equality, which I come across quite often.
This solution can be simplified by using the same IoC container as for the UI, as you have pointed in your question. I agree that it is not a good idea to pass the IUnityContainer
to the ViewModels directly. I can't see anything wrong about using the container for resolving the ViewModels, though. I would recommend to build a simple service, which caches ViewModel instances and creates new ViewModels by using the IUnityContainer
.
The following code is pseudo code, mixing a bit of MEF with a bit of Autofac syntax, but I think it get's clear what it's about:
An interface for getting the ViewModels:
public interface IViewModelProvider
{
T GetViewModel<T>(object model);
}
An implementation which imports the Unity container and uses it for resolving ViewModels which have not been cached already. The ViewModelCache
is something like an advanced dictionary you have to build yourself.
[Export(typeof(IViewModelProvider))]
public class ViewModelProvider : IViewModelProvider
{
private IUnityContainer _container;
private ViewModelCache _viewModelCache;
[ImportingConstructor]
public ViewModelProvider(IUnityContainer container)
{
_container = container;
}
public T GetViewModel<T>(object model)
{
if (_viewModelCache.Contains<T>(model))
return _viewModelCache.Get<T>(Model);
var viewModel = _container.Resolve<T>();
viewModel.Model = model;
_viewModelcache.Cache(viewModel);
return viewModel;
}
}
then this service can be injected into your ViewModels and the ViewModels can create their own children ViewModels and don't have to care about whether these already exist because or need to be created.
Hope this helps. It's a broad topic, so please ask if you have any particular questions.