SimpleIoc - может ли он каждый раз предоставлять новый экземпляр?
Насколько я понимаю, SimpleIoc использует метод GetInstance для извлечения экземпляра зарегистрированного класса. Если экземпляр не существует, он создаст его. Однако этот экземпляр кэшируется и всегда извлекается, что имитирует шаблон синглтона.
Я думаю, что нет необходимости хранить экземпляр ViewModel в памяти, если существует небольшая вероятность того, что этот ViewModel понадобится дважды, поэтому я хотел бы создавать его каждый раз, когда это необходимо. Если у нас есть фабрика для ViewModels, у нас будет свойство, подобное этому:
public MyViewMOdel MyViewModel
{
get { return SimpleIoc.Default.GetInstance<MyViewModel>(); }
}
в этом используется шаблон синглтона, который, я думаю, не является наилучшей практикой во всех случаях. Чтобы обойти эту проблему, я делаю это:
public MyViewModel MyViewModel
{
get { return new MyViewModel(SimpleIoc.Default.GetInstance<ISomeInterface>()); }
}
У этого есть недостаток: если я когда-нибудь изменю конструктор для MyViewModel, мне нужно будет обновить и это свойство. Ничего страшного, но все же есть какая-то зависимость.
Как вы справляетесь с этим сценарием, и что-то мне не хватает? и почему было решено не возвращать незарегистрированный экземпляр.
И еще один вопрос: в сеансе глубокого погружения MVVM Лоран использует метод GetInstance сразу после регистрации определенной модели ViewModel, чтобы, по его словам, убедиться, что в контейнере уже есть экземпляр этой модели ViewModel. Почему именно это необходимо? Если вы выбираете ViewModel через ViewModelLocator, вы создадите его при необходимости. Так почему я хочу, чтобы они были созданы заранее?
3 ответа
Каждый раз вы можете получать разные экземпляры, передавая разные ключи методу GetInstance. Однако экземпляры будут кэшироваться, поэтому, если вы не хотите хранить их в кэше, вам необходимо вызвать Unregister с соответствующим ключом.
В демоверсии я создавал виртуальную машину заранее, потому что MainVM отправлял сообщения на SecondaryVM. Поскольку регистрация в Messenger выполняется в конструкторе SecondaryVm, его необходимо создать, прежде чем он сможет начать получать сообщения. Messenger великолепен, потому что он очень отделен, но это один из этих случаев, когда вам нужно проделать дополнительную работу, чтобы компенсировать разделение: SecondaryVM является целью сообщений, даже если MainVM не получает на него никаких ссылок.
Надеюсь, это имеет смысл. Ура, Лоран
После борьбы с SimpleIoC для предоставления новых экземпляров каждый раз, когда запрашивается определенный тип, и обнаружение, что эта функция не реализована (принятый выше метод на основе ключей не подходит для сценариев, в которых вы хотите сказать, выполнить операцию базы данных и сбросить соединение каждый раз), я придумал относительно приличное решение, сочетающее IoC с шаблоном Factory: создайте класс, который берет на себя ответственность за создание новых экземпляров определенного типа через функцию:
class MyObjectFactory: IMyObjectFactory
{
public MyObject CreateObject()
{
return new MyObject();
}
}
Создайте интерфейс для класса фабрики MyObject:
public interface IMyObjectFactory
{
MyObject CreateObject();
}
Затем настройте контейнер IoC для предоставления фабрики любым классам, которые используют экземпляры MyObject:
SimpleIoc.Default.Register<IMyObjectFactory, MyObjectFactory>();
Теперь любой класс, требующий нового экземпляра MyObject, объявит свое требование MyObjectFactory (вместо требования MyObject) в конструкторе для внедрения конструктора:
public class MyObjectUser
{
MyObject _myObject;
public MyObjectUser(IMyObjectFactory factory)
{
_myObject = factory.CreateObject();
}
}
Таким образом, я думаю, что вы не связаны ограничениями шаблона Factory и имеете все преимущества контейнеров IoC и Constructor Injection, что также позволяет обойти ограничения SimpleIoC.
SimpleIOC - это то, что это... простой контейнер IOC. У него будут некоторые недостатки... но вы не связаны с ним, вы всегда можете использовать другой контейнер ICO (например, Unity, Autofac, Castle, ...).
Как утверждает Лоран, он смоделировал свой SimpleIOC на этом контейнере. Он также упоминает этот контейнер как источник своего вдохновения.
Однако помните, что вы не обязаны использовать отдельный контейнер с MVVM. В нескольких моих проектах я использовал Unity, но все остальные контейнеры IOC будут одинаково хороши, это зависит от требований, предпочтений клиентов и - если все остальное не сработает - от простого старого личного удовольствия.
После прочтения всех очень познавательных и качественных ответов в этой ветке я хотел бы только указать на что-то, возможно, не настолько продвинутое технологически, но я думаю, что очень важно поместить в ветку о настройке.
IoC Container
: Я думаю, что написание собственного IoC-контейнера - одна из самых простых задач в ООП, связанных с моими собственными библиотеками, и я уверен, что это полезно с точки зрения образования. Я не помещаю здесь никаких руководств, потому что, надеюсь, все, кто прочитал мое мнение, знают
Google Search
или аналогичные инструменты;-)