Страницы

Поиск по вопросам

пятница, 13 декабря 2019 г.

Dependency Injection в WPF

#c_sharp #wpf #dependencies #dependency_injection


Добрый вечер! У меня появился такой вопрос. Как правильно реализовать внедрение зависимости
в WPF? 
Проблема вот в чем. Скажем у меня есть приложение которое включает в себя несколько
окон в каждом из которых нужно привязывать например интерфейс IFoo к классу Foo. Я
имогу сделать привязку конкретных типов к интерфейсам для каждого окна по отдельности
но проблема в том что разные окна используют одинаковые интерфейсы и если делать привязку
для каждого окна по отдельности то получится дублирование кода - дл\я каждого окна
будут выполняться одинаковые привязки, и при этом я не смогу изменить привязку только
из одного места в программе. Это нужно будет делать для каждого окна по отдельности.
Тогда рушится весь Dependency Injection.  А вот как это сделать так чтобы привязка
осуществлялась для всего приложения один раз и была известна ото всюду я не знаю.     


Ответы

Ответ 1



Прежде всего вам надо использовать паттерн Model-View-ViewModel в своем WPF-приложении, если вы еще не делаете этого. В приложении, реализованном с применением MVVM, окна содержат только XAML-разметку, а вся логика находится в моделях представлений. Именно в моделях представлений вам придется использовать внедрение конструктора для получения зависимостей. Вот так может выглядеть конструктор модели представления окна, который принимает в качестве зависимости IFoo: public class SomeWindowViewModel { public SomeWindowViewModel(IFoo foo) { } } Далее. Корневым объектом в вашем графе зависимостей будет модель представления главного окна приложения. Это будет первый объект, который создаст контейнер внедрения зависимоcтей и он должен быть создан раньше чем будет показано главное окно. Модель представления главного окна может принимать в качестве зависимостей IFoo и любые другие необходимые объекты: public class MainWindowViewModel { public MainWindowViewModel(IFoo foo, ISomeService service /*и т.д.*/) { } } Корень компоновки, то место где вы единственный раз определите все привязки, и соберете ваш граф объектов, должен находится в точке входа приложения. В случае с WPF-приложением точкой входа является класс App, и здесь есть небольшая проблема. По умолчанию файл App.xaml выглядит вот так: Здесь строчка StartupUri="MainWindow.xaml" декларативно указывает фреймворку, что при запуске приложения должно быть создано и отображено окно MainWindow.xaml. Чтобы взять контроль в свои руки вы должны удалить строку StartupUri="MainWindow.xaml" и создать окно сами в методе OnStartup класса App. Теперь вы контролируете процесс создания окна и можете привязать к нему его ViewModel. При этом не следует создавать модель представления главного окна самостоятельно. Вместо этого надо получить ее из контейнера внедрения зависимоcтей, позволив тем самым контейнеру самостоятельно построить граф объектов. На примере CastleWindsor это будет выглядеть так: public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); // создаем контейнер внедрения зависимостей var container = new WindsorContainer() // подключаем модуль, в котором прописаны привязки // (этот модуль - то самое место, где мы прописываем привязки // единственный раз) container.Install(new MainInstaller()) // теперь, когда контейнер осведомлен о привязках, // мы можем запросить у него ViewModel, и контейнер вернет // ее нам, самостоятельно разрешив все зависимости var viewModel = container.Resolve(); // теперь можно показывать главное окно var mainWindow = new MainWindow(); mainWindow.DataContext = viewModel; mainWindow.Show(); } }

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

Отправить комментарий