ViewModelLocator с дочерними контейнерами IOC?

#silverlight #ioc-container #viewmodel #mvvm-light #viewmodellocator

#silverlight #ioc-контейнер #viewmodel #mvvm-light #viewmodellocator

Вопрос:

Как вы реализуете шаблон ViewModelLocator при использовании дочерних контейнеров IOC? Типичная реализация локатора выглядит примерно так:

 public IViewModel ViewModel
{
   get { return Services.ServiceLocator.GetInstance<IViewModel>(); }
}
  

где сервисы.ServiceLocator — это статическое свойство, доступное только для чтения. Но это не работает, если вы используете дочерние контейнеры. Вот мое определение сервисов.ServiceLocator с использованием дочерних контейнеров:

 public static IServiceLocator ServiceLocator
{
    get { return RootContext.ServiceLocator; }
}
  

Очевидно, что это неверно: мои введенные зависимости будут поступать из корневого контейнера вместо дочернего контейнера. (Дочерний контейнер создается и загружается с помощью чего-то другого, кроме моего текущего представления. Таким образом, мой текущий вид может автоматически подключаться из дочернего контейнера.)

Итак, как вы получаете правильный контейнер в сценарии с несколькими контейнерами? Стандартный ответ заключается в том, чтобы внедрить его в конструктор, но это кажется невозможным с ViewModelLocator: для этого требуется конструктор по умолчанию, чтобы его можно было сконструировать из XAML.

Мне также нужно решение, которое работает как в Silverlight 4, так и в WPF 4.0, поскольку я работаю над составным приложением PRISM (таким образом, без расширений разметки). Так получилось, что я использую Unity в качестве контейнера IOC. О, и решение должно работать в Blend (то есть оно не должно препятствовать созданию новой модели представления во время разработки, которая обходит контейнер IoC).

Ответ №1:

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

Для доступа к дочернему контейнеру у вас может быть свойство, которое возвращает дочерний контейнер — либо одноэлементный экземпляр, либо временный (т. Е. новый) экземпляр. Однако, если вы хотите совместимый доступ, вам следует учитывать, что дочерний контейнер должен находиться в ваших ресурсах, чтобы привязываться к нему во время разработки.

В любом случае вы должны убедиться, что экземпляры ваших ViewModels должным образом очищены, чтобы не возникло утечек памяти.

Редактировать: В вашем конкретном случае это может быть полезно. Хотя у меня не было времени посмотреть видео, Лоран сказал мне, что он демонстрирует способ динамической загрузки модели представления. Я надеюсь, что это действительно поможет вам!

Комментарии:

1. Я немного прояснил первоначальный вопрос. Часть, на которой я застрял, заключается в следующем: если я нахожусь на n уровнях в глубине дочерних контейнеров, как я могу получить n-й контейнер, чтобы выполнить автоматическую проводку в view model locator? n определяется во время выполнения и зависит от вида: второй вид может иметь глубину m уровней, а третий вид может иметь глубину x уровней. Таким образом, определение статических шлюзов для каждого уровня непрактично (не говоря уже о том, что у вас может быть несколько дочерних элементов на каждом уровне, так как бы вы разрешили правильный контейнер на этом уровне).

2. Пока дочерние контейнеры IoC и VML выглядят как несовместимые шаблоны. Я бы так хотел, чтобы мне доказали, что я ошибался.