Проблема с впрыском IoC-MEF - PullRequest
       31

Проблема с впрыском IoC-MEF

1 голос
/ 18 декабря 2010

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

UML моего приложения выглядит следующим образом: http://i54.tinypic.com/2n1b4mx.png

Мой сценарий: я создаюв view-model-1 (в проекте LogOnViewModel) новый view-model-2 (в моем проекте MessengerViewModel) с методом shell-view-model.

Мне нужно передать объект из view-model-1 вконструктор view-model-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);
  }
 }

}

Запустите View-Model.Класс LogOnViewModel:

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.

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

1 Ответ

1 голос
/ 19 декабря 2010

Используемый вами шаблон фабрики не создает никаких композиций, кроме создания самого класса 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.

.другой аккаунт вместо вашего текущего

...