Где разместить и настроить контейнер IoC в приложении WPF?
Я работаю над средним WPF-приложением (MVVM), которое должно быть расширяемым и поддерживаемым в будущем. Таким образом, я решил использовать контейнер IoC (Unity в этом случае), чтобы поддерживать гибкость.
Однако я не уверен, где разместить и настроить Unity в приложении WPF.
Я предполагаю, что контейнер должен быть доступен глобально, поэтому он должен, вероятно, перейти к классу Application. Но должен ли я сделать это как статическое свойство? Должен ли я настраивать его в обработчике событий Application_Startup()?
Например:
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public static UnityContainer MyUnityContainer;
private void Application_Startup(object sender, StartupEventArgs e)
{
// instantiate and configure Unity
}
}
Таким образом, я смогу получить доступ к контейнеру из любого места приложения через статическое свойство:
App.MyUnityContainer
Я предполагаю, что это один из способов сделать это, но я не уверен, есть ли более эффективные методы для этой проблемы, особенно для приложений WPF.
Ответы
Ответ 1
Посмотрите на Корневой шаблон композиции. То, что вы хотите сделать, это инициализировать его в обработчике событий Startup и забыть о его существовании для остальной части приложения.
Вы пытаетесь реализовать шаблон локатора службы, который, по мнению многих является более низким решением эта проблема.
Ответ 2
Позвольте мне опубликовать то, что я сделал, и, надеюсь, это поможет людям. Правильно, если что-то не так!: P
Думаю, мы бы посмотрели что-то вроде этого:
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
UnityContainer myUnityContainer = new UnityContainer();
//make sure your container is configured
myUnityContainer.RegisterType<ISomeDependency, SomeDependencyImplementation>();
myUnityContainer.RegisterType<IMainWindow, MainWindow>();
myUnityContainer.Resolve<IMainWindow>().Show();
}
}
public partial class MainWindow : Window, IMainWindow
{
private ISomeDependency _someDependency;
public MainWindow(ISomeDependency someDependency)
{
_someDependency = someDependency;
}
}
Обратите внимание, что нет глобальных или одиночных элементов, контейнер выживает до тех пор, пока MainWindow делает, и все зависимости, стоящие за этой точкой входа дальше в график композиции, автоматически разрешаются, пока контейнер знает о них.
Ответ 3
В соответствии с новой версией контейнера Unity мы должны также зарегистрировать его собственный экземпляр, чтобы получить его в виде моделей через инсталляцию конструктора.
Файл App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
var unityIoC = new UnityContainer();
unityIoC.RegisterTypes(AllClasses.FromAssembliesInBasePath(), WithMappings.FromMatchingInterface, WithName.Default);
unityIoC.RegisterInstance(typeof(IUnityContainer), unityIoC);
}
Показать класс модели
[InjectionConstructor]
public MyViewModel(IUnityContainer container)
{
}
Теперь контейнер единства будет доступен для нас в модели вида и может быть использован для разрешения.