Search code examples
c#mvvmcaliburn.microfactory-pattern

MEF and Caliburn.Micro ViewModelFactory with Parameters


I've been working with Caliburn.Micro and MEF and I'm trying to get a viewmodelfactory implementation working. What I'm attempting is to create a chain of ViewModels for a dialog window (each ViewModel instantiates one or more viewmodels to generate the overall layout of the window). I'm having trouble importing the viewmodelfactory correctly; I can get it without a problem using [ImportingConstructor], however when I try to use [import] I end up with a null reference exception against viewModelFactory.

The "ViewModelFactory" which I have implemented is as per:

http://blog.pglazkov.com/2011/04/mvvm-with-mef-viewmodelfactory.html

and I'm trying to import the viewmodel as per the following:

[Import]
public IViewModelFactory viewModelFactory { get; set; } 

and IViewModelFactory itself has an export declared (and works correctly with [ImportingConstructor]

[Export(typeof(IViewModelFactory))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ViewModelFactory : IViewModelFactory

Attempt 2

MY next effort was trying to add an instance of ViewModelFactory into the composition container:

protected override void Configure()
{
    var catalog =
    new AggregateCatalog(
            AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());

    container = new CompositionContainer(catalog);

    var batch = new CompositionBatch();

    batch.AddExportedValue<IWindowManager>(new WindowManager());
    batch.AddExportedValue<IEventAggregator>(new EventAggregator());
    batch.AddExportedValue<IViewModelFactory>(new ViewModelFactory());
    batch.AddExportedValue(container);

    container.Compose(batch);
}

However this results in an error within the ViewModelFactory, stating that the composition container which is Lazy loaded is null.

I'm trying to find a solution that will allow me to still use the Factory approach, as it allows me to use constructor parameters which are currently required as part of my viewmodels.

EDIT

I was able to get this to work by having an "Initialise" function within my viewmodels, using [ImportingConstructor] on my ViewModels with a constructor that only contains the IViewModelFactory declaration. However, this now required me to instantiate the viewmodel and make a call to the "initialise" function whenever I am creating these, so a more elegant approach would be great.

Thanks.


Solution

  • Managed to implement a different solution to this, which was to use:

    IoC.Get<*ViewModelName*>();
    

    Still haven't worked out why the [Import] by itself didn't work, however this certainly solved the issue for me.