Проблема с вводом IoC-MEF

Я использую Caliburn.Micto в качестве фреймворка MVVM для моего приложения WPF, а также MEF для инъекций.

UML моего приложения выглядит так: http://i54.tinypic.com/2n1b4mx.png

Мой сценарий таков: я создаю в модели представления-1 (в проекте LogOnViewModel) новую модель представления-2 (в моем проекте - MessengerViewModel) с методом оболочки-представления-модели.

Мне нужно передать объект из модели представления-1 в конструктор модели представления-2.

Я использую MEF в классе инъекций из внешней сборки, которая загружается в класс boostraper.

При создании новых моделей представления я использую абстрактный фабричный шаблон, вот моя реализация:

 /// <summary>
 /// Factory interfaces
 /// </summary>
 public interface IViewModelFactory
 {

  ILogOnViewModel CreateLogOnViewModel(IShellViewModel shellViewModel);
  IMessengerViewModel CreateMessengerViewModel(IShellViewModel shellViewModel, PokecAccount account);
 }

 /// <summary>
 /// Concrent implementation of factory
 /// </summary>
 [Export(typeof(IViewModelFactory))]
 public class DefaulFactoryViewModel:IViewModelFactory
 {
  #region Implementation of IViewModelFactory

  //create start up view-model
  public ILogOnViewModel CreateLogOnViewModel(IShellViewModel shellViewModel)
  {
   return new LogOnViewModel(shellViewModel);
  }

  //this method create new view model
  //it is used in LogOnViewModel
  public IMessengerViewModel CreateMessengerViewModel(IShellViewModel shellViewModel, PokecAccount account)
  {
   return new MessengerViewModel(shellViewModel, account);
  }

 }

Я использую этот фабричный класс в своей модели представления оболочки. Класс Shell-view-model выглядит следующим образом:

/// <summary>
 /// Shell model interface
 /// </summary>
 public interface IShellViewModel
 {
  //create start up view-model
  void ShowLogOnView();

  //this method create new view model
  //it is used in LogOnViewModel
  void ShowMessengerView(PokecAccount account);
 }

 [Export(typeof(IShellViewModel))]
 public class ShellViewModel : Conductor<IScreen>, IShellViewModel
 {
  //factory interface
  private readonly IViewModelFactory _factory;

  [ImportingConstructor]
  public ShellViewModel(IViewModelFactory factory)
  {
   //inject factory
   _factory = factory;

   //show startup view model
   ShowLogOnView();
  }

  public void ShowLogOnView()
  {
   //create LogOnViewModel class with factory
   var model = _factory.CreateLogOnViewModel(this);

   ActivateItem(model);
  }

  /// <summary>
  /// Create MessengerViewModel
  /// </summary>
  /// <param name="account">account in this case is send from LogOnViewModel class </param>
  public void ShowMessengerView(PokecAccount account)
  {
   //create MessengerViewModel class with factory
   var model = _factory.CreateMessengerViewModel(this, account);

   ActivateItem(model);
  }
 }

}

Запустите модель представления. Класс Логонвиевмодел:

public interface ILogOnViewModel : IScreen, IDataErrorInfo
{
 string Nick { get; set; }
 string Password { get; set; }
 bool CanLogOn { get; set; }
 void LogOn(string nick, string password);
}


public class LogOnViewModel : Screen, ILogOnViewModel
{
 /// <summary>
 /// inject class from external assembly
 /// after creation of this class is still null
 /// </summary>
 [Import]
 public IPokecConnection PokecConn { get; set; }


 private readonly IShellViewModel _shellViewModel = null;

 private PokecAccount _account = null;

 public LogOnViewModel(IShellViewModel shellViewModel)
 {
  _shellViewModel = shellViewModel;
  _account = new PokecAccount();
 }


 //CREATE NEW VIEW MODEL
 public void CreateNewView()
 {
  //create new view-model (MessengerViewModel)
  _shellViewModel.ShowMessengerView(_account);
 }

}

Класс MessengerViewModel:

public interface IMessengerViewModel : IScreen
{
 BitmapImage AvatarImage { get; set; }
 string AvatarStatus { get; set; }
 KeyValuePair<string, Friend> SelectedFriend { get; set; }
}

public class MessengerViewModel : Screen, IMessengerViewModel
{


 [Import]
 private IPokecService _pokecService;
 [Import]
 private IPokecConnection _pokecConn;
 private IShellViewModel _shellViewModel = null;
 private PokecAccount _account = null;

 public MessengerViewModel(IShellViewModel shellViewModel, PokecAccount account)
 {
  _shellViewModel = shellViewModel;
  _account = account;
 }
}

У меня проблема с инъекцией в класс модели представления. При создании классов модели представления я использую фабричный шаблон, но мне нужно вводить в этот класс также из внешней сборки.

Например: после создания класса LogOnVieModel IPokecConnection PokecConn{ get; set;} по-прежнему null.

Какое наиболее подходящее решение в моем случае? Где проблема? Спасибо за помощь.


person JMI    schedule 18.12.2010    source источник


Ответы (1)


Используемый вами фабричный шаблон не выполняет никакой композиции, кроме самого класса ViewScreenModel. Вам нужно сообщить MEF, чтобы он составлял ваши модели представления, если они не создаются с помощью внедрения. Обновите класс фабрики, чтобы создать экземпляр перед его возвратом;

public ILogOnViewModel CreateLogOnViewModel
{
    var model = new LogOnViewModel();
    var container = // set this to your reference of CompositionContainer
    container.ComposeParts(model);

    return model;
}

...где Bootstapper.Container — это ваш экземпляр CompositionContainer.

С другой стороны, почему вы создали другую учетную запись вместо использования текущей.

person Matthew Abbott    schedule 19.12.2010