Проблема с MEF - ExportFactory <T>в Caliburn.Micro - PullRequest
0 голосов
/ 04 января 2011

Я использую MEF в Caliburn.Micro для классов моделей экспорта.Я хотел бы использовать класс ExportFactory вместо атрибута Export, потому что я пытаюсь решить ту же проблему, как описано здесь: Проблема уничтожения объекта с MEF

Я пытаюсь решить эту проблему, пример:

Некоторая модель представления - окно WPF:

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

Я открываю экран чата с оконным менеджером в другом классе модели представления:

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

Затем закрываюэкран, но объект этого класса все еще жив.Я пробую ту же проблему, как описано здесь: Проблема уничтожения объекта с MEF

У меня есть модель представления - это окно WPF

СЦЕНАРИЙ / РЕШЕНИЕ

У меня есть 3 модели просмотра / экран:

  • LogOnViewModel - пользовательский контроль
  • MessengerViewModel - пользовательский контроль
  • ChatViewModel - окно WPF

Код этих моделей представлений приведен здесь:

//#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
{

}

Моя оболочка выглядит следующим образом:

  //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);
        }

    }

Я хотел бы использовать класс ExportFactory для создания класса моделей представления.Я пытаюсь реализовать ту же логику, что и здесь: http://mef.codeplex.com/wikipage?title=PartCreator.

Поэтому я создаю собственный контроллер для создания классов моделей представления:

Вот оно:

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;
    }
}

Я импортирую ViewModelsControlerкласс в этих классах:

  • ShellViewModel
  • MessengerViewModel

И хотел бы метод класса ViewModelsControler при создании класса моделей представления.- Элемент списка

Я не знаю, что я делаю плохо, если я пытаюсь скомпилировать этот код a, я получаю эту ошибку:

Не удалось найти экземпляры контракта Spirit.ViewModels.IShellViewModel.Staktrace: at Spirit.BootStraper.MefBootStrapper.GetInstance (введите serviceType, ключ String) в C: \ Users \ Jan \ Documents \ Visual Studio 2010 \ Projects \ C # \ Pokec_Messenger \ ver.beta \ Pokec__Messenger \ Spirit_Caliburn_Micro_v1ot \ MeBoStra.cs: ​​строка 59 в Caliburn.Micro.IoC.GetT в 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: строка 33 в Caliburn.Micro.Bootstrapper`1.DisplayRootView () в 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: строка 175 в Caliburn.Micro.Bootstrapper.OnStartup (отправитель объекта, StartupEventArgs e) в C: \ Users \ Jan \ Documents \ Visual Studio 2010 \ Projects \ C # \ Pokec_Messenger \ ver.бета \ Pokec__Messenger \ Caliburn_Micro_Completed \ CaliburnMicro \ src \ Caliburn.Micro.Silverlight \ Bootstrapper.cs: строка 128 в System.Windows.Application.OnStartup (StartupEventArgs e) в System.Windows.Application. <. Ctor> b__1 (объект не используется) в System.Windows.Threading.ExceptionWrapper.InternalRealCall (обратный вызов делегата, аргументы объекта, Int32 numArgs) в MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen (Источник объекта, Метод делегата, Аргументы объекта, Int32 numArgs, Delegate catchHandler)

Если я использую атрибут Export в классе модели представления создания, это работает хорошо.

Примерно так:

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

И оболочка:

   [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);
        }

    }

Где может быть проблема?В классе MEF Boosterper?Я использую классическую MEF Boostrape: http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/08/caliburn-micro-soup-to-nuts-pt-2-customizing-the-bootstrapper.aspx

Спасибо за совет, ваше время и помощь.

1 Ответ

1 голос
/ 04 января 2011

Вам все еще нужен экспорт для классов, которые вы хотите экспортировать. Использование ExportFactory позволяет создавать несколько экземпляров, но это не работает, если у вас нет атрибута экспорта для объекта, для которого вы хотите создать экземпляры.

...