IoC - конструктор принимает значение времени выполнения в качестве одного параметра и службы в качестве другого - PullRequest
11 голосов
/ 23 марта 2011

У меня есть приложение WPF, которое при запуске просматривает файловую систему для некоторых файлов конфигурации

Для каждого файла конфигурации, который он находит, он отображает некоторую информацию в отдельном окне

Каждое окно имеет связанный объект ViewModel, который привязан к текстовому тексту Windows

Таким образом, новая ViewModel создается для каждого файла конфигурации. Объект, представляющий данные в файле конфигурации, передается в конструктор viewmodels

Однако модель View также имеет другие зависимости, передаваемые в конструктор

Код выглядит примерно так (в загрузчике, инициированном из app.xaml)

foreach (WindowConfig config in ConfigManager.GetConfigs())
{
    IMyService svc = new MyService();

    //change to resolve from IoC container
    MyViewModel vm = new MyViewModel(config, svc);

    Window1 view = new Window1();

    view.DataContext = vm;

    window.show();
}

Я хочу использовать контаинер Castle IoC для устранения этих зависимостей. Я знаю, как сделать это для IMyService, но как я могу сделать это для определенного класса, который был создан из файла конфигурации?

спасибо

Ответы [ 2 ]

8 голосов
/ 23 марта 2011

Всегда помните, что в коде приложения извлечение из контейнера никогда не является решением. Код приложения не должен знать, что в игре находится DI-контейнер .

Общее решение, когда вам нужно разрешить зависимость на основе значения времени выполнения, состоит в использовании абстрактной фабрики .

В вашем случае, фабрика может выглядеть так (при условии, что ваши config переменные являются строками:

public interface IViewModelFactory
{
    IViewModel Create(string configuration);
}

Теперь вы можете внедрить IViewModelFactory как отдельную зависимость в класс, который перебирает файлы конфигурации.

Чтобы реализовать IViewModelFactory, вы можете сделать это вручную или использовать Типизированная фабрика Касла Виндзора , чтобы реализовать ее для вас.

2 голосов
/ 23 марта 2011

Вы можете передать параметры в Виндзор, которые он должен использовать при разрешении конструктора, используя перегрузку IWindsorContainer.Resolve, которая принимает IDictionary в качестве параметра. В этом словаре ключом должно быть имя параметра, а значением должен быть объект, который будет использоваться в качестве значения параметра:

var arguments = new Dictionary<string,object> {{ "config", config }, { "service", svc } };
var viewModel = container.Resolve<MyViewModel>(arguments);
...