Где разместить и настроить контейнер 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)
{
}

Теперь контейнер единства будет доступен для нас в модели вида и может быть использован для разрешения.