Как использовать Ninject в приложении WPF

Я знаком с MVC, но я пытаюсь изучить WPF с помощью Ninject. Может ли кто-нибудь дать мне пример или ссылку?

Ответы

Ответ 1

Как я уже сказал в своем комментарии к вашему OP, вся необходимая информация доступна в документации Ninject. Тем не менее, можно утверждать, что легко потеряться в своей обширной документации, если вы не знакомы с Ninject и/или DI.

Есть несколько обучающих онлайн, из которых этот, который я считал особенно информативным. Пока он дает пример с помощью console application, принципы работы Ninject остаются неизменными.

Независимо от типа вашего приложения вы настраиваете свой контейнер в точке входа приложения;

  • Консольное приложение - Main
  • WPF - App (если вы не используете фреймворк, в этом случае вы можете предоставить настраиваемый загрузчик)
  • ASP.NET - не знаю, возможно, кто-то может просветить меня.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ Я не утверждаю, что являюсь авторитетом на Ninject или DI, ниже - просто быстрый пример того, как я понимаю, что эти два объекта могут использоваться в сочетании друг с другом.

Например, ради, давайте работать с примерами, представленными в документации Ninject.

1) Создайте приложение WPF с именем NinjectIoC

2) Используйте Nuget для добавления ссылки на проект Ninject

3) Откройте App.xaml и удалите свойство StartupUri из элемента Application, чтобы ваш App.xaml выглядел следующим образом:

<Application x:Class="NinjectIoC.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>

    </Application.Resources>
</Application>

Причина, по которой мы это делаем, заключается в том, что свойство StartupUri сообщает приложению WPF, какой элемент управления пользовательским интерфейсом первоначально отображается при запуске приложения. Мы будем использовать Ninject для отображения нашего начального элемента управления пользовательского интерфейса.

4) Откройте App.xaml.cs. Здесь мы будем настраивать Ninject container или Kernel для использования терминологии Ninject. Мы override метод OnStartup приложения, чтобы мы могли сконфигурировать наш container и впоследствии инициализировать приложение так, как хотелось бы. Обновите содержимое своего App.xaml.cs, чтобы выглядеть следующим образом:

namespace NinjectIoC
{
    using Ninject;
    using System.Windows;

    public partial class App
    {
        private IKernel container;

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            ConfigureContainer();
            ComposeObjects();
            Current.MainWindow.Show();
        }

        private void ConfigureContainer()
        {
            this.container = new StandardKernel();
            container.Bind<IWeapon>().To<Sword>().InTransientScope();
        }

        private void ComposeObjects()
        {
            Current.MainWindow = this.container.Get<MainWindow>();
            Current.MainWindow.Title = "DI with Ninject";
        }
    }
}

Краткое объяснение:

4.1) OnStartup - Override the OnStartup method so that we may configure our container` и инициализировать приложение по своему желанию.

4.2) ConfigureContainer - Сообщите нашему container, как мы хотели бы разрешить наши конкретные типы. Это гораздо больше, чем я показал в этом примере, однако, это гораздо больше, чем я показал. Существуют такие темы, как Multi Binding, Соглашения о привязке и Модули ядра, о которых вы лучше всего узнаете из официальной документации .

4.3) ComposeObjects - Удалив свойство StartupUri из App.xaml, мы должны сообщить приложению, какой элемент управления UI мы хотели бы использовать для MainWindow. Наряду с тем, чтобы наш container использовал MainWindow в качестве нашего MainWindow, мы также устанавливаем свойство Title. Снова вы можете сделать другие задачи здесь для ручной компоновки объектов.

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

5) Далее откройте MainWindow.xaml, затем скопируйте и вставьте следующее:

<Window x:Class="NinjectIoC.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="78" Width="362">
    <Grid>
        <Button Content="Button" HorizontalAlignment="Left" Margin="269,10,0,0" VerticalAlignment="Top" Width="75" Click="Attack"/>
        <TextBox x:Name="Target" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" VerticalAlignment="Top" Width="254"/>
    </Grid>
</Window>

Я не буду объяснять это выше, поскольку должно быть очевидно, что происходит.

6) Наконец откройте MainWindow.xaml.cs и обновите его следующим образом:

namespace NinjectIoC
{
    using System.Windows;

    public partial class MainWindow
    {
        private readonly IWeapon weapon;

        public MainWindow(IWeapon weapon)
        {
            this.weapon = weapon;
            InitializeComponent();
        }

        private void Attack(object sender, RoutedEventArgs e)
        {
            this.weapon.Hit(this.Target.Text);
        }
    }

    public class Sword : IWeapon
    {
        public void Hit(string target)
        {
            MessageBox.Show(@"I swing and thrust my sword about like a mad man at " + target);
        }
    }

    public interface IWeapon
    {
        void Hit(string target);
    }
}

Снова я сделаю это краткое изложение, поскольку то, что происходит выше, не имеет ничего общего с конфигурацией Ninject, и оно должно снова быть очевидным, что происходит.

Главное, что следует заметить в приведенном выше, - это argument, который ожидает конструктор MainWindow; IWeapon. Вы можете спросить себя, как это решить, поскольку я не создаю конкретную реализацию Weapon где угодно?

Хорошо во время ConfigureContainer метода в App.xaml.cs мы сообщили container, как мы хотим, чтобы он разрешал зависимости для IWeapon:

container.Bind<IWeapon>().To<Sword>().InTransientScope();

Приведенное выше указывает container, что везде, где он встречает зависимость для IWeapon, мы хотели бы предоставить экземпляр Weapon. После запроса container решения (Get) нашего начального элемента управления MainWindow, используя следующее:

Current.MainWindow = this.container.Get<MainWindow>();

container рассмотрел его конструкторы и определил конструктор с большинством аргументов, которые он понял. В этом примере конструктор потребовал реализации IWeapon и oh look, container знает, как разрешить эту зависимость, потому что мы рассказали ей, как это сделать раньше в ConfigureContainer.

Предполагая, что ни вы, ни я не допустили ошибок с указанным выше кодом, нажатие F5 должно запустить приложение, и вы увидите небольшое окно с TextBox и Button. Введите что-то в TextBox, затем нажмите Button, и вы увидите элемент управления MessageBox, информирующий вас о том, что вы взмахнули своим мечом как "mad man" тем, кто или что вы ввели в TextBox.


Существует гораздо больше для Ninject и DI, чем я описал здесь. Например, есть целые книги по теме DI, такие как этот Марк Сееман.

Надеемся, что вышеизложенное даст вам основную отправную точку, где искать и куда идти дальше, с вашими приключениями с помощью Ninject и DI.