我最近啓動了一個遵循MVVM模式的WPF項目,當然。我試圖一次只解析視圖模型的對象圖(在組合根中,即在應用程序的Startup事件處理程序中),以便不讓任何其他類依賴於IoC容器:從組合根解析交互式請求的視圖模型?
public partial class App : Application
{
private void OnStartup(object sender, StartupEventArgs e)
{
// Composition Root
var container = new UnityContainer();
container.RegisterType<IResidentListViewModel, ResidentListViewModel>();
container.RegisterType<IMainViewModel, MainViewModel>();
container.RegisterType<IDataService, DataService>();
var mainWindow = new MainWindow(container.Resolve<IMainViewModel>());
Current.MainWindow = mainWindow;
mainWindow.Show();
}
}
ResidentListViewModel又取決於IDataService:
private readonly IDataService dataService;
public ResidentListViewModel(IDataService dataService)
{
if (dataService == null)
throw new ArgumentNullException("dataService");
this.dataService = dataService;
}
這是不是一個問題,因爲容器將解決依賴正常的。
然而,ResidentListviewModel有命中IDataService一個居民財產:
private readonly ObservableCollection<IResidentViewModel> residents = new ObservableCollection<IResidentViewModel>();
public ObservableCollection<IResidentViewModel> Residents
{
get
{
if (this.residents == null)
LoadResidents();
return this.residents;
}
}
麻煩的開始,當數據被加載:
private async Task LoadResidents()
{
if (!IsLoading)
{
IsLoading = true;
var models = await this.dataService
.ListResidents();
var viewModels = models
.OrderBy(m => m.Name)
.ThenBy(m => m.Vorname)
.Select(m => new ResidentViewModel(m.Z_PF, string.Format("{0}, {1}", m.Name, m.Vorname)));
residents.Clear();
foreach (var viewModel in viewModels)
residents.Add(viewModel);
IsLoading = false;
}
}
我知道,我知道,反覆添加到一個ObservableCollection是一個不走,但請在這裏忍受我。在那看到那個閃亮的'新'關鍵字?這是真正的罪魁禍首。我不知道如何在不退服服務定位器('實例工廠')的情況下襬脫它,而服務定位器反過來又是一種反模式,根據我最喜歡的DI書籍作者Mark Seemann(是的,我確實有這本書,會推薦給任何C#開發人員)。
我當然可以注入虛擬機本身的列表,但這會將數據檢索移動到合成根目錄(聽起來像一個壞主意),我可以輕鬆想出一個場景,用戶選擇一個條目和代碼必須根據選擇檢索數據,讓我回到原點。
所以問題是:有沒有辦法解決這個問題,從同一個單一的調用組合根?
使用容器和構造函數注入而不是靜態(讀取:全局)服務定位器註冊工廠:) –
+1,儘管AFAICT,residentViewModelFactory不是工廠方法,而是一個抽象工廠。 –
@MarkSeemann:你的意思是''ResidentViewModelFactory'(class)是一個*抽象工廠*,而'CreateInstance'是所謂抽象工廠的工廠方法* –