Prism, соединяя Views и ViewModels с Unity, пытаясь понять это - PullRequest
11 голосов
/ 23 декабря 2011

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

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

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

public QuestionnaireView() 
{
    InitializeComponent(); 
}

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

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

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

public QuestionnaireView() 
{
    InitializeComponent(); 
}

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

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

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

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

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

  2. В первом примере, подключающем View и ViewModel с помощью конструктора, не упоминается Unity всех, поэтомудействительно ли здесь используется Unity?

  3. Есть ли какие-либо преимущества использования инъекций на основе свойств по сравнению с инъекциями на основе контрагентов, или это одно и то же?

    Первая часть текста гласит: «Как правило, вы определяете интерфейс в модели представления, чтобы конкретный конкретный тип модели представления можно было отделить от представления», а затем приводите пример.Тем не менее, этот пример вообще не упоминает интерфейсы.Что здесь происходит, я что-то упустил?

1 Ответ

13 голосов
/ 23 декабря 2011

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

В вашем примере модель представления имеет тип QuestionnaireViewModel, который является конкретным классом.Поскольку это конкретный класс, когда вы разрешаете представление с помощью container.Resolve<QuestionnaireView>(), Unity создает для вас модель представления, вызывая 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<>().Таким образом, вы можете вставлять элементы в свойства даже после создания, чего вы не можете сделать с помощью инжектора конструктора.

...