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

Jan 4, 2011 at 3:26 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.