Silverlight ViewModelLocator, определенный в app.xaml, требует ссылки на контейнер DI - PullRequest
1 голос
/ 02 сентября 2010

У меня есть класс ViewModelLocator, который я определяю в app.xaml, который используется моими представлениями для привязки данных к правильному ViewModel.

DataContext="{Binding HomeViewModel, Source={StaticResource Locator}}"

Я использую Prism и Unity, и мой класс ViewModelLocator нуждается вссылка на контейнер уровня приложения.

Я хотел внедрить IUnityContainer в ctor объекта ViewModelLocator, но экземпляр ViewModelLocator создается из app.xaml с использованием ctor без параметров.

Есть ли предпочтительный способчтобы получить доступ к контейнеру уровня приложения - для всех других классов в приложении я просто использую инъекцию ctor, чтобы получить глобальный контейнер.

То, что я в данный момент делаю для ViewModelLocator, определяет статическую переменную в моем классе BootStrapperхранить контейнер.Я создаю контейнер путем переопределения метода CreateContainer в UnityBootStrapper.

protected override IUnityContainer CreateContainer()
{
    BootStrapper.DIContainer = base.CreateContainer();
    return BootStrapper.DIContainer;
}

Затем в классе ViewModelLocator я просто ссылаюсь на свойство BootStrapper.DIContainer, чтобы зарегистрировать мои viewmodels

BootStrapper.DIContainer.RegisterType<IShellViewModel, DesignShellViewModel>();

Это прекрасно работает, но это единственное место в приложении, которое должно ссылаться на это статическое свойство на загрузчике - и хотело бы избавиться от него, если это возможно.

спасибо Майкл

Ответы [ 2 ]

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

У меня была такая же проблема при конвертации моего приложения Silverlight RIA Business для использования легкого инструментария Prism, Unity и MVVM.Я придумал этот обходной путь, который заключается в том, чтобы просто позволить App.xaml создать экземпляр моего класса ViewModelLocator, и во время события запуска приложения я удаляю этот экземпляр, который он создал из ресурсов приложения, и повторно добавляю экземпляр, используя контейнера Unity.Разрешить метод .

  1. Зарегистрировать VML в Unity.

Boostrapper.cs: (класс UnityBootstrapper)

protected override void ConfigureContainer()
{
    Container.RegisterType<ViewModelLocator>(new ContainerControlledLifetimeManager());
    base.ConfigureContainer();
}
  1. Используйте конструктор или внедрение свойства в VML для IUnityContainer.Здесь я использую свойство инъекции.Также обратите внимание, что конструктор по умолчанию без параметров необходим, потому что App.xaml собирается создать экземпляр своего собственного экземпляра, который мы просто выбрасываем.

ViewModelLocator.cs: (используется для смешиваемости)

public class ViewModelLocator
{
    [Dependency]
    public IUnityContainer Container { get; set; }

    public ViewModelLocator() { }

....

}

  1. Удалите и повторно добавьте VML к ресурсам приложения.Замените строковый литерал «Локатор» тем, что вы называете своим VML в разделе ResourceDictionary App.xaml.

App.xaml.cs:

private void Application_Startup(object sender, StartupEventArgs e)
{
    Bootstrapper bootstrapper = new Bootstrapper();
    bootstrapper.Run();

    Resources.Remove("Locator");
    Resources.Add("Locator", bootstrapper.Container.Resolve<ViewModelLocator>());
}

Ваш теперь взведенный, заблокированныйи готов качаться ..

0 голосов
/ 01 сентября 2011

Я думал, что буду следить за этим, так как он не был помечен как ответ.

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

Наличие свойства Container в классе ViewModelLocator, помеченном с помощью DependencyAttribute, означает, что класс может разрешить свои зависимости после создания,Поэтому в моем загрузчике я перезаписываю ConfigureContainer и добавляю следующий код:

var vml = Application.Current.Resources["ViewModelLocator"] as ViewModelLocator;

Container.BuildUp(typeof(ViewModelLocator), vml);

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

Для меня это гораздо более чистое решение.Конечно, это не смешиваемо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...