Problem with MEF - ExportFactory<T> in Caliburn.Micro

Jan 4, 2011 at 3:25 PM
Edited Jan 4, 2011 at 3:28 PM

Hi, I use MEF in Caliburn.Micro for export view models classes. I would like use ExportFactory class rather than Export attribute because I try solve same problem as is described here: Object destruction problem with MEF

I try solve this problem, example:

Some view model - WPF window:

 

[Export(typeof(IChatViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChatViewModel : Screen, IViewModelIdentity,
IChatViewModel, IHandle<Rp>, IHandle<DetailData>
{}

 

I open chat screen with window manager in some other view model class.

 

private IWindowManager _windowManager;
var chatScreen = IoC.Get<IChatViewModel>();
_windowManager.Show(chatScreen);

 

Then I close screen, but object of this class is still alive. I try same problem as is described here: Object destruction problem with MEF

I have view model - it is WPF window

SCENARIO / SOLUTION

I have 3 view models/screen:

  • LogOnViewModel - user control
  • MessengerViewModel - user control
  • ChatViewModel - WPF Window

Code of these view models is here:

 

//#1 screen - user control
public class LogOnViewModel : Screen, ILogOnViewModel
{
private IShellViewModel _shell;

[ImportingConstructor]
public LogOnViewModel(IShellViewModel shell)
{
_shell = shell;
}

//....

//Active #2 screen Messenger screen
_shell.ShowMessenger(_account);

//....
}

//#2 screen - user control
public class MessengerViewModel : Screen,IMessengerViewModel
{
private IViewModelsControler _viewModelControler;
private IWindowManager _windowManager;

[ImportingConstructor]
public MessengerViewModel(IViewModelsControler viewModelControler, IWindowManager windowManager)
{
_windowManager = windowManager;
_viewModelControler = viewModelControler;

}

//...

//Open #3 sceen - WPF window
var vindow = _viewModelControler.CreateChatViewModel();
_windowManager.Show(window);

//...
}

//#3 screen - WPF window
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChatViewModel : Screen, IChatViewModel
{

}

 

My shell look like this:

 

 //SHELL is WPF window  
[Export(typeof(IShellViewModel))]
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IShellViewModel
{
[Import]
public IViewModelsControler ViewModelControler{ get; set;}

protected override void OnInitialize()
{
ShowLogOn();
base.OnInitialize();
}

public void ShowLogOn()
{
//var vm = IoC.Get<ILogOnViewModel>();
var vm = ViewModelControler.CreateLogOnViewModel();
ActivateItem(vm);
}

public void ShowMessenger(Account account)
{
ActiveItem.Deactivate(true);
//var vm = IoC.Get<IMessengerViewModel>();
var vm = ViewModelControler.CreateMessengerViewModel();
vm.Account = account;
ActivateItem(vm);
}

}

 

I would like use ExportFactory class for creation view models class. I try implement same logic as here: http://mef.codeplex.com/wikipage?title=PartCreator.

So I create own controler for creation view models classes:

Here ist it:

 

public  interface IViewModelsControler
{
ILogOnViewModel CreateLogOnViewModel();
IMessengerViewModel CreateMessengerViewModel();
IChatViewModel CreatChatViewModel();
}

[Export(typeof(IViewModelsControler))]
public class ViewModelsControler:IViewModelsControler
{
[Import]
public ExportFactory<ILogOnViewModel> LogOnViewFactory { get; set; }

public ILogOnViewModel CreateLogOnViewModel()
{
return LogOnViewFactory.CreateExport().Value;
}

[Import]
public ExportFactory<IMessengerViewModel> MessengerViewFactory { get; set; }

public IMessengerViewModel CreateMessengerViewModel()
{
return MessengerViewFactory.CreateExport().Value;
}

[Import]
public ExportFactory<IChatViewModel> ChatViewFactory { get; set; }

public IChatViewModel CreatChatViewModel()
{
return ChatViewFactory.CreateExport().Value;
}
}

 


Hi, I use MEF in Caliburn.Micro for export view models classes. I would like use ExportFactory class rather than Export attribute because I try solve same problem as is described here: Object destruction problem with MEF

I try solve this problem, example:

Some view model - WPF window:

[Export(typeof(IChatViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChatViewModel : Screen, IViewModelIdentity,
IChatViewModel, IHandle<Rp>, IHandle<DetailData>
{}
 

I open chat screen with window manager in some other view model class:

private IWindowManager _windowManager;
var chatScreen = IoC.Get<IChatViewModel>();
_windowManager.Show(chatScreen);
 

Then I close screen, but object of this class is still alive. I try same problem as is described here: Object destruction problem with MEF

I have view model - it is WPF window

SCENARIO / SOLUTION

I have 3 view models/screen:

  • LogOnViewModel - user control
  • MessengerViewModel - user control
  • ChatViewModel - WPF Window

Code of these view models is here:

//#1 screen - user control
public class LogOnViewModel : Screen, ILogOnViewModel
{
private IShellViewModel _shell;

[ImportingConstructor]
public LogOnViewModel(IShellViewModel shell)
{
_shell = shell;
}

//....

//Active #2 screen Messenger screen
_shell.ShowMessenger(_account);

//....
}

//#2 screen - user control
public class MessengerViewModel : Screen,IMessengerViewModel
{
private IViewModelsControler _viewModelControler;
private IWindowManager _windowManager;

[ImportingConstructor]
public MessengerViewModel(IViewModelsControler viewModelControler, IWindowManager windowManager)
{
_windowManager = windowManager;
_viewModelControler = viewModelControler;

}

//...

//Open #3 sceen - WPF window
var vindow = _viewModelControler.CreateChatViewModel();
_windowManager.Show(window);

//...
}

//#3 screen - WPF window
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChatViewModel : Screen, IChatViewModel
{

}
 

My shell look like this:

 
 //SHELL is WPF window  
[Export(typeof(IShellViewModel))]
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IShellViewModel
{
[Import]
public IViewModelsControler ViewModelControler{ get; set;}

protected override void OnInitialize()
{
ShowLogOn();
base.OnInitialize();
}

public void ShowLogOn()
{
//var vm = IoC.Get<ILogOnViewModel>();
var vm = ViewModelControler.CreateLogOnViewModel();
ActivateItem(vm);
}

public void ShowMessenger(Account account)
{
ActiveItem.Deactivate(true);
//var vm = IoC.Get<IMessengerViewModel>();
var vm = ViewModelControler.CreateMessengerViewModel();
vm.Account = account;
ActivateItem(vm);
}

}
 

I would like use ExportFactory class for creation view models class. I try implement same logic as here: http://mef.codeplex.com/wikipage?title=PartCreator.

So I create own controler for creation view models classes:

Here ist it:

public  interface IViewModelsControler
{
ILogOnViewModel CreateLogOnViewModel();
IMessengerViewModel CreateMessengerViewModel();
IChatViewModel CreatChatViewModel();
}

[Export(typeof(IViewModelsControler))]
public class ViewModelsControler:IViewModelsControler
{
[Import]
public ExportFactory<ILogOnViewModel> LogOnViewFactory { get; set; }

public ILogOnViewModel CreateLogOnViewModel()
{
return LogOnViewFactory.CreateExport().Value;
}

[Import]
public ExportFactory<IMessengerViewModel> MessengerViewFactory { get; set; }

public IMessengerViewModel CreateMessengerViewModel()
{
return MessengerViewFactory.CreateExport().Value;
}

[Import]
public ExportFactory<IChatViewModel> ChatViewFactory { get; set; }

public IChatViewModel CreatChatViewModel()
{
return ChatViewFactory.CreateExport().Value;
}
}




I import ViewModelsControler class in these classes:

  • ShellViewModel
  • MessengerViewModel

And would like method of class ViewModelsControler on creation view models class. - List item

I don’t know what I do bad, if I try compile this code a I get this error:

*Could not locate any instances of contract Spirit.ViewModels.IShellViewModel. Staktrace: at Spirit.BootStraper.MefBootStrapper.GetInstance(Type serviceType, String key) in C:\Users\Jan\Documents\Visual Studio 2010\Projects\C#\Pokec_Messenger\ver.beta\Pokec__Messenger\Spirit_Caliburn_Micro_v1.0\BootStraper\MefBootStrapper.cs:line 59 at Caliburn.Micro.IoC.GetT in C:\Users\Jan\Documents\Visual Studio 2010\Projects\C#\Pokec_Messenger\ver.beta\Pokec__Messenger\Caliburn_Micro_Completed\CaliburnMicro\src\Caliburn.Micro.Silverlight\IoC.cs:line 33 at Caliburn.Micro.Bootstrapper`1.DisplayRootView() in C:\Users\Jan\Documents\Visual Studio 2010\Projects\C#\Pokec_Messenger\ver.beta\Pokec__Messenger\Caliburn_Micro_Completed\CaliburnMicro\src\Caliburn.Micro.Silverlight\Bootstrapper.cs:line 175 at Caliburn.Micro.Bootstrapper.OnStartup(Object sender, StartupEventArgs e) in C:\Users\Jan\Documents\Visual Studio 2010\Projects\C#\Pokec_Messenger\ver.beta\Pokec__Messenger\Caliburn_Micro_Completed\CaliburnMicro\src\Caliburn.Micro.Silverlight\Bootstrapper.cs:line 128 at System.Windows.Application.OnStartup(StartupEventArgs e) at System.Windows.Application.<.ctor>b__1(Object unused) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)*

If I use Export attribute on creation view model class, it works good.

Something like this:

[Export(typeof(ILogOnViewModel))]
public class LogOnViewModel : Screen,ILogOnViewModel
{}

And shell:

 

   [Export(typeof(IShellViewModel))]
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IShellViewModel
{
protected override void OnInitialize()
{
ShowLogOn();
base.OnInitialize();
}

public void ShowLogOn()
{
var vm = IoC.Get<ILogOnViewModel>();
//var vm = _viewModelControler.CreateLogOnViewModel();
ActivateItem(vm);
}

public void ShowMessenger(Account account)
{
ActiveItem.Deactivate(true);
var vm = IoC.Get<IMessengerViewModel>();
//var vm = _viewModelControler.CreateMessengerViewModel();
vm.Account = account;
ActivateItem(vm);
}

}

 

 

Where can be problem? In MEF boostraper class? I use clasic MEF boostrape: http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/08/caliburn-micro-soup-to-nuts-pt-2-customizing-the-bootstrapper.aspx

Thank for advice, your time and help.