0

我目前正在嘗試學習如何使用Unity和Caliburn Micro實現MVVM。在其他地方尋求幫助後,我仍然不確定如何正確設置構造器注入。由於我在MVVM或其他方面缺乏專業知識,我不知道這是不是工作。具有多個參數的Unity/Caliburn Micro,注入構造函數

我的問題是我想在兩個IScreen對象中傳入我的主窗口(shell)類,當用戶點擊一個按鈕時可以導航到這個類。這裏是我的MainWindowViewModel類構造函數的代碼:

private IScreen campaignViewModel, stringsViewModel; 
public MainWindowViewModel(IScreen campaignViewModel, IScreen stringsViewModel) 
{ 
    this.campaignViewModel = campaignViewModel; 
    this.stringsViewModel = stringsViewModel; 
    ActiveItem = this.campaignViewModel; 
} 

這是我用我的引導程序代碼(統一)類:

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方法有關,但我不確定。

任何幫助將不勝感激!

謝謝。

回答

1

在您的構造函數中,您定義了兩次相同的接口。

DI框架如何知道哪個是?答:它不能。

所以不是該使用的2個接口:

public MainWindowViewModel(ICampaignScreen campaignViewModel, IStringsScreen stringsViewModel) 

你可以讓這兩個從IScreen繼承:

public interface ICampaignScreen : IScreen 

也不需要添加任何IScreen - 他們根本爲框架提供了區分它們的手段。

+0

那麼,我只是將注入改爲: 新的InjectionConstructor(typeof(CampaignsViewModel),typeof(StringsViewModel))並已完成此操作。我嘗試了爲每個視圖模型創建接口的方法,但我無法將其編譯。不過謝謝。 – stuartmclark

+0

回想起你的回答,我意識到你事實上是正確的,即使我所做的工作,它實際上是一個黑客,而不是實際上獲得統一解決接口。爲每個View模型創建一個從IScreen派生的接口是正確的舉措。謝謝。 – stuartmclark

1

更改:

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

而且這個工作。我不知道它是否違反任何規則或原則,但現在起作用。