Unity / Caliburn Micro, инжекторный конструктор с несколькими параметрами - PullRequest
0 голосов
/ 04 июля 2011

В настоящее время я пытаюсь научиться внедрять 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 ]

1 голос
/ 04 июля 2011

Изменено:

 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)));

И это сработало. Я не знаю, нарушает ли это какие-либо правила или принципы, но пока работает.

1 голос
/ 04 июля 2011

В вашем конструкторе вы определяете один и тот же интерфейс дважды.

Как фреймворк DI узнает, что есть что ??Ответ: он не может.

Поэтому вместо этого используйте 2 интерфейса:

 public MainWindowViewModel(ICampaignScreen campaignViewModel, IStringsScreen stringsViewModel)

Вы можете сделать оба этих объекта наследующими от IScreen:

 public interface ICampaignScreen : IScreen

и ни к чему не нужно добавлять что-либо в IScreen - они просто предоставляют платформе средства различать их.

...