Динамические данные с IoC контейнером

202
02 ноября 2018, 02:10

Изучаю тему IoC и DI. Всё вроде понял зачем как и почему пока не дошел до IoC контейнера Unity. Непонятно следующее. Объясняю на примере WPF MVVM: У нас есть некие книги в базе данных, MainWindow c соответствующим ему MainWindowViewModel и DetailWindow с соответствующим DetailWindowViewModel, который принимает себе в конструктор книгу. Естественно и тот и другой ViewModel мы регистрируем в контейнере. На главном окне имеем поле ввода названия книги, заполнив которое производится поиск книги в БД и пользователю открывается окно с детальной информацией о выбранной книге. Как это сделать? Ведь регистрируя тип данных в контейнере можно только что-нибудь захардкодить и не более. Не могу понять как это должно всё работать в жизни. Или вся эта концепция применяется только в каких-то отдельных случаях когда надо передать в качестве зависимости что-нибудь типа репозитория без конкретных данных?

Как вариант, конечно можно передавать детали о книге не через конструктор, а вызвав после создания DetailWindowViewModel какой-нибудь метод Init(IBook book), но на мой взгляд - это неправильно и небезопасно, т.к. без данных книги этот класс не имеет смысла, а конструктор как раз и нужен для того чтобы не забылись данные без которых класс не может работать.

Не поймите не правильно, я не критикую, я просто пытаюсь понять как это использовать и получается пока не очень.

Answer 1

Можно передавать параметры в UnityContainer.Resolve. При этом есть один минус: студия не подскажет если вы забудете передать параметры в конструктор через resolve. Избежать ошибок в этом месте можно проверяя в конструкторе корректность входных параметров и выдачей исключения, и применяя юнит-тесты

Answer 2

Рассмотрим сферического коня в вакууме

class Foo {
    private Bar bar;
    public Foo() {
       this.bar = new Bar();
    }
}
class Bar {
    private string name = "bar";
    public getName() {
        return this.name;
    }
}

и вроде бы всё круто. Но вдруг мы захотим чтобы Foo.bar был другого класса? И почему Foo решил, что bar может быть только класса Bar?

Перепишем класс Foo и Bar

class Foo {
    private IBar bar;
    public Foo(IBar bar) {
       this.bar = bar;
    }
}
class Bar : IBar {
    private string name = "bar";
    public string getName() {
        return this.name;
    }
}
interface IBar {
    string getName();
}

Вот. Теперь мы решаем какой bar будет у Foo, а не сам Foo. На вид инверсия управления. Плюсом мы теперь зависим от интерфейса, а не реализации.

Контейнер же нам позволяет не передавать вручную в конструктор Foo экземпляр IBar. Он такие дела разруливает за нас.

READ ALSO
Как считать файл из сетевой папки в Xamarin Android(c#)

Как считать файл из сетевой папки в Xamarin Android(c#)

Например, у меня есть txt файл на удалённом компьютере в его открытой сетевой папкеНужно локально считать этот файл

249
Вопрос про парсер CsQuery

Вопрос про парсер CsQuery

Всех приветствую, вопрос такой, изучаю этот парсер, вот страница, которую я хочу разобратьВот мой код

235
Как из C# удалить переход на другой лист в Word?

Как из C# удалить переход на другой лист в Word?

Соединяю несколькоdocx документов в один

923