Правильный способ использования DI при создании новых объектов в Collection - PullRequest
0 голосов
/ 14 сентября 2018

MVVM, используя PRISM 6 и Unity.

Bootstrapper заботится о создании начального View, который, в свою очередь, автоматически подключается к ViewModel (т. Е. View Model разрешается, и о его DI заботятся).

Теперь модель просмотра имеет коллекцию других моделей представления.

Эта коллекция может быть добавлена ​​с помощью пользовательского ввода, скажем, нажатием кнопки.

Для просмотра моделей в коллекции требуется доступ к единственному файлу, который мне необходим для управления «Рабочим пространством» (пути к папкам с изображениями и т. Д.). Поэтому я также хотел бы, чтобы в создании этих объектов был внедрен этот синглтон "Рабочая область"

В методе, который создаст новую ViewModel, как правильно использовать DI / IoC для его создания?

Единственный способ, которым я вижу это (опасно говорить «только», я знаю, поэтому я прошу помощи):

  1. Добавление контейнера Unity в модель представления, которая содержит коллекции, а затем разрешить новые модели просмотра при нажатии кнопки. Новые View View Models будут настроены с зависимостью от интерфейс для объекта "Рабочая область".
  2. Создайте new Просмотр модели при нажатии кнопки и передайте «Рабочее пространство» в конструкторе (конечно, Рабочее пространство должно быть DI'd в родительской модели представления для передачи вниз).

Я прочитал несколько мест, в которых прохождение Контейнера через DI, так что можно использовать Resolve <>, не является "правильным".

Может ли это помочь в создании общей фабрики? Это все еще заставляет меня сдать контейнер, теперь он просто в форме фабрики ...

public T factory<T>(IContainer _container)
{
    return _container.Resolve<T>();
}

1 Ответ

0 голосов
/ 15 сентября 2018

Часто, когда я читаю о DI, это трактуется как все и конец всему. Я чаще всего интенсивно использую IoC даже в своих небольших и простых проектах, однако, это всего лишь шаблон и место, как и все остальное.

Книга Microsoft Press Адаптивный код с помощью C # хорошо объясняет SOLID, оправдывает его использование, охватывает различные формы DI и затраты / выгоды каждого метода. Для меня в этом много смысла: управление ростом проекта и работа с внешними зависимостями.

Я бы НЕ передавал UnityContainer чему-либо за пределами моего загрузчика, кроме системы, которая абстрагирует и разбивает процесс начальной загрузки / модульности. В дополнение к замечаниям, которые вы сделали по этому поводу, Unity является сторонней зависимостью от вашего приложения, как и все остальное, и я бы очень избирательно отнесся к тому (если есть), к которому я себя привязываю.

Для вашего примера выше я бы использовал простую фабрику. Вы можете абстрагировать это так, как вам нравится, но хорошим компромиссом будет освобождение вашей основной ViewModel от бремени необходимости создавать своих собственных потомков.

При использовании DI нет ничего плохого в том, чтобы создавать экземпляры самостоятельно, где это уместно. Самым подходящим местом, конечно, является завод. Я бы не стал создавать универсальную фабрику, как вы сказали, это в основном похоже на обход контейнера IoC. Вместо этого определите типизированную фабрику:

public interface IWorkspaceItemViewModelFactory
{
    WorkspaceItemViewModel CreateWorkspaceItem();
}

Реализация этого может выглядеть примерно так:

public class WorkspaceItemViewModelFactory
{
    private readonly IWorkspaceManager _workspaceManager;

    public WorkspaceItemViewModelFactory(IWorkspaceManager workspaceManager)
    {
        _workspaceManager = workspaceManager;
    }

    public WorkspaceItemViewModel CreateWorkspaceItem()
    {
        return new WorkspaceItemViewModel(_workspaceManager);
    }
}

Этот класс является информационным экспертом с единственной ответственностью за создание WorkspaceItemViewModel экземпляров. Он имеет право использовать ключевое слово new и знает о WorkspaceItemViewModel зависимостях. Возможно, вы захотите изолировать ViewModel с помощью интерфейса, но в вашем случае это значение может быть очень небольшим. В конечном счете, вы используете IoC, DI и интерфейсную сегрегацию по определенной причине, и когда они перестают приносить пользу вашему конкретному приложению, их использование становится помехой.

Ваша модель представления может использовать что-то вроде:

public class ExampleViewModel : ViewModelBase
{
    public ExampleViewModel(IWorkspaceItemViewModelFactory workspaceItemViewModelFactory)
    {
        AddItemCommand = new ActionCommand(() =>
        {
            var newItem = workspaceItemViewModelFactory.CreateWorkspaceItem();
            WorkspaceItems.Add(newItem);
        });
    }

    public ICommand AddItemCommand { get; }

    public ObservableCollection<WorkspaceItemViewModel> WorkspaceItems { get; } = new ObservableCollection<WorkspaceItemViewModel>();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...