Unity/Caliburn Micro, инжекторный конструктор с несколькими параметрами
В настоящее время я пытаюсь научиться внедрять MVVM с использованием Unity и Caliburn Micro. После поиска помощи в другом месте я все еще не уверен в том, как правильно настроить инжектор конструктора. Я не знаю, если это не работает из-за моего отсутствия опыта в MVVM или что-то еще.
Моя проблема в том, что я хочу передать два объекта IScreen в класс главного окна (оболочки), по которому можно перемещаться, когда пользователь нажимает кнопку. Вот код для конструктора в моем классе MainWindowViewModel:
private IScreen campaignViewModel, stringsViewModel;
public MainWindowViewModel(IScreen campaignViewModel, IScreen stringsViewModel)
{
this.campaignViewModel = campaignViewModel;
this.stringsViewModel = stringsViewModel;
ActiveItem = this.campaignViewModel;
}
Вот код, который я использую в своем классе Bootstrapper(Unity):
private static IUnityContainer BuildContainer()
{
IUnityContainer result = new UnityContainer();
result
.RegisterInstance(result)
.RegisterInstance<IWindowManager>(new WindowManager())
.RegisterInstance<IEventAggregator>(new EventAggregator());
result
.RegisterType<IScreen, CampaignsViewModel>()
.RegisterType<IScreen, StringsViewModel>()
.RegisterType<MainWindowViewModel>(new InjectionConstructor(typeof(IScreen), typeof(IScreen)));
return result;
}
protected override object GetInstance(Type service, string key)
{
var result = unity.Resolve(service, key);
if (result == null)
throw new Exception(string.Format("Could not locate any instance of contract {0}", service));
return result;
}
При этом MainWindowViewModel получает два экземпляра StringsViewModel. Хотя, если бы я вставил ключ в утверждение:
result.RegisterType<IScreen, StringsViewModel>("StringsView");
Затем он проходит в двух экземплярах CampaignsViewModel. Я не знаю, как указать InjectionConstructor, что я хочу, чтобы он передавался в одном экземпляре CampaignViewModel и StringsViewModel. У меня есть ощущение, что это может быть связано с методом GetInstance, но я не уверен.
Любая помощь будет принята с благодарностью!
Благодарю.
2 ответа
В вашем конструкторе вы определяете один и тот же интерфейс дважды.
Как структура DI узнает, что есть что? Ответ: не может.
Поэтому вместо этого используйте 2 интерфейса:
public MainWindowViewModel(ICampaignScreen campaignViewModel, IStringsScreen stringsViewModel)
Вы можете сделать оба из этих наследников от IScreen:
public interface ICampaignScreen : IScreen
и ни к чему не нужно добавлять что-либо в IScreen - они просто предоставляют платформе средства для их различения.
Изменен:
result
.RegisterType<IScreen, CampaignsViewModel>()
.RegisterType<IScreen, StringsViewModel>()
.RegisterType<MainWindowViewModel>(new InjectionConstructor(typeof(IScreen), typeof(IScreen)));
Для того, чтобы:
result
.RegisterType<IScreen, CampaignsViewModel>()
.RegisterType<IScreen, StringsViewModel>()
.RegisterType<MainWindowViewModel>(new InjectionConstructor(typeof(CampaignsViewModel), typeof(StringsViewModel)));
И это сработало. Я не знаю, нарушает ли это какие-либо правила или принципы, но пока работает.