Я ничего не знаю о WPF или MVVM, но ваш вопрос в основном о том, как вытащить вещи из контейнера, не используя Service Locator (или контейнер напрямую) повсюду, верно?
Еслида, я могу показать вам пример.
Дело в том, что вместо этого вы используете фабрику, которая использует контейнер внутри.Таким образом, вы фактически используете контейнер только в одном месте.
Примечание: я буду использовать пример с WinForms, а не привязанный к конкретному контейнеру (потому что, как я уже сказал, я не знаю WPF ... и я используюCastle Windsor вместо NInject), но поскольку ваш основной вопрос не связан конкретно с WPF / NInject, вам будет легко "перенести" мой ответ на WFP / NInject.
Фабрика выглядитнапример:
public class Factory : IFactory
{
private readonly IContainer container;
public Factory(IContainer container)
{
this.container = container;
}
public T GetStuff<T>()
{
return (T)container.Resolve<T>();
}
}
Основная форма вашего приложения получает эту фабрику с помощью инжектора конструктора:
public partial class MainForm : Form
{
private readonly IFactory factory;
public MainForm(IFactory factory)
{
this.factory = factory;
InitializeComponent(); // or whatever needs to be done in a WPF form
}
}
Контейнер инициализируется при запуске приложения и разрешается основная форма (поэтому он получает фабрику через инжектор конструктора).
static class Program
{
static void Main()
{
var container = new Container();
container.Register<MainForm>();
container.Register<IFactory, Factory>();
container.Register<IYourRepository, YourRepository>();
Application.Run(container.Resolve<MainForm>());
}
}
Теперь основная форма может использовать фабрику для извлечения таких вещей, как ваше хранилище, из контейнера:
var repo = this.factory.GetStuff<IYourRepository>();
repo.DoStuff();
Если у вас есть больше форм и вы хотите использовать фабрику оттудаКроме того, вам просто нужно ввести фабрику в эти формы, как в основную форму, зарегистрировать дополнительные формы при запуске, а также открыть их из основной формы с фабрикой.
Это то, что вы хотелизнаете?
РЕДАКТИРОВАТЬ:
Рубен, конечно, вы правы.Моя ошибка.
Все, что было в моем ответе, было старым примером того, что я где-то лежал, но спешил, когда опубликовал свой ответ, и недостаточно внимательно прочитал контекст моего старого примера.
Мой старый пример включал в себя основную форму, из которой вы можете открыть любую другую форму приложения. Это для чего была фабрика, поэтому вам не нужно вводить каждую другую форму с помощью инжектора конструктора в основную форму.
Вместо этого вы можете использовать фабрику, чтобы открытьлюбая новая форма:
var form = this.factory.GetStuff<IAnotherForm>();
form.Show();
Конечно, вам не нужна фабрика, чтобы просто получить хранилище из формы, если хранилище передается в форму с помощью инжектора конструктора.
Если вашприложение состоит только из нескольких форм, вам вообще не нужна фабрика, вы также можете просто передавать формы через конструктор:
public partial class MainForm : Form
{
private readonly IAnotherForm form;
// pass AnotherForm via constructor injection
public MainForm(IAnotherForm form)
{
this.form = form;
InitializeComponent(); // or whatever needs to be done in a WPF form
}
// open AnotherForm
private void Button1_Click(object sender, EventArgs e)
{
this.form.Show();
}
}
public partial class AnotherForm : Form
{
private readonly IRepository repo;
// pass the repository via constructor injection
public AnotherForm(IRepository repo)
{
this.repo= repo;
InitializeComponent(); // or whatever needs to be done in a WPF form
// use the repository
this.repo.DoStuff();
}
}