Призма, соединяющая Views и ViewModels с Unity, пытаясь понять это

Создание модели представления и просмотра с использованием единства

Использование Unity в качестве контейнера для инъекций зависимостей аналогично использованию MEF, и как на основе свойств, так и на основе конструктора поддерживается. Основное отличие состоит в том, что типичные типы неявно обнаруженные во время выполнения; вместо этого они должны быть зарегистрированный в контейнере.

Как правило, вы определяете интерфейс на модели представления, поэтому вид конкретный конкретный тип модели может быть отделен от вида. Для Например, представление может определять его зависимость от модели представления посредством конструктор, как показано здесь. С#

public QuestionnaireView() 
{
    InitializeComponent(); 
}

public QuestionnaireView(QuestionnaireViewModel viewModel) : this() 
{
    this.DataContext = viewModel;
}

По умолчанию параметр-less конструктор необходим, чтобы позволить просмотру работать во время разработки инструменты, такие как Visual Studio и Expression Blend.

В качестве альтернативы вы можете определить свойство модели просмотра только для записи на как показано здесь. Unity создаст требуемую модель просмотра и вызовите средство настройки свойств после создания представления. С#

public QuestionnaireView() 
{
    InitializeComponent(); 
}

[Dependency] 
public QuestionnaireViewModel ViewModel 
{
    set { this.DataContext = value; } 
}

Тип модели вида зарегистрирован в контейнере Unity, как показано Вот. С#

IUnityContainer container;
container.RegisterType<QuestionnaireViewModel>();

Затем представление может быть представлено через контейнер, как показано Вот. С#

IUnityContainer container;
var view = container.Resolve<QuestionnaireView>();
  • Если я не укажу последнюю часть кода, касающуюся регистрации ViewModel и создания экземпляра представления, и просто используйте один из двух способов подключения ViewModel к представлению здесь (используя конструктор или используя свойство) кажется, ViewModel и View кажется, что все работает нормально. Итак, в чем же нуждается код, регистрирующий ViewModel и создающий представление View?

  • Первый пример, связанный с View и ViewModel с использованием конструктора, не имеет упоминания о единстве всех, так что Unity действительно используется здесь?

  • Есть ли какие-либо преимущества использования инъекции на основе свойств над инъекцией на основе конструктора или они точно такие же?

  • В первой части текста говорится: "Обычно вы определяете интерфейс в модели представления, поэтому конкретный конкретный тип модели просмотра может быть отделен от представления", а затем дает пример. Однако этот пример вообще не упоминает о интерфейсах. Что здесь происходит, я чего-то не хватает?

Ответ 1

Чтобы ответить на вопросы 1 и 4

В вашем примере модель просмотра имеет тип QuestionnaireViewModel, который является конкретным классом. Поскольку это конкретный класс, когда вы разрешаете представление с помощью container.Resolve<QuestionnaireView>(), единство будет создавать экземпляр модели просмотра для вас, вызывая container.Resolve<QuestionnaireViewModel>() за кулисами.

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

public QuestionnaireView(IQuestionnaireViewModel viewModel)
{
    this.DataContext = viewModel;
}

Теперь, когда ваш конструктор получает интерфейс, а не класс как параметр, Unity не знает, какую реализацию интерфейса вы хотите использовать. Чтобы сообщить Unity, вам необходимо зарегистрировать свою модель просмотра в контейнере:

container.RegisterType<IQuestionnaireViewModel, QuestionnaireViewModel>();

Итак, теперь, когда вы разрешаете свое представление, Unity будет искать, какой класс он должен использовать как реализацию IQuestionnaireViewModel, см. его QuestionnaireViewModel и использовать его.

Чтобы ответить на вопрос 2

Используется Unity, поскольку для того, чтобы конструктор мог получить свои параметры, вам нужно разрешить представление с помощью контейнера. Unity не используется, если вы сами создаете представление, используя new QuestionnaireView(), т.е. Никакой конструктор или вложение свойств не произойдет.

Чтобы ответить на вопрос 3

Я думаю, что это в основном вопрос того, что более удобно и где вам нужно использовать введенных членов. Много раз вы просто хотите установить локальную переменную в конструкторе и не создать свойство только для выполнения инъекции.

Одна хорошая вещь о введении свойств - это факт, что вы можете использовать метод container.BuildUp() для экземпляров, созданных с помощью new, а не container.Resolve<>(). Таким образом, вы можете вводить члены в свойства даже после создания - это то, что вы не можете сделать с введением конструктора.