IoC - Constructor принимает значение времени выполнения как один параметр, а сервис - другой

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

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

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

Итак, для каждого файла конфигурации создается новый 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 contaoiner для решения этих зависимостей. Я знаю, как это сделать для IMyService, но как я могу это сделать для определенного класса, который был создан из файла конфигурации?

спасибо

Ответ 1

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

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

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

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

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

Чтобы реализовать IViewModelFactory, вы можете сделать это вручную или использовать Castle Windsor Типизированный factory Средство, чтобы реализовать его для вас.

Ответ 2

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

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