我真的剛剛開始使用MVVM,IoC和依賴注入,我碰到了一個絆腳石,我不知道如何解決,但我明白爲什麼會發生。MVVM - 在ViewModels中使用實體
我使用Castle Windsor的DI和IoC功能以及MVVM Light作爲WPF應用程序中的MVVM框架。使用this tutorial我已經設法讓Castle Windsor創建一個MainPageViewModel
,它有一個IGroupRepository
注入到構造函數中。我在Castle Windsor註冊了這個模擬實現。
以下是除構造函數外MainPageViewModel
類中唯一的其他代碼。
public ObservableCollection<GroupViewModel> Groups
{
get
{
var groupVms = new ObservableCollection<GroupViewModel>();
IEnumerable<Group> groups = _repository.GetAllGroups();
foreach (Group g in groups)
{
var vm = new GroupViewModel(g);
groupVms.Add(vm);
}
return groupVms;
}
}
其目的是爲存儲庫中的每個組創建一個視圖模型。然而,這樣做會導致溫莎城堡給以下異常:
無法創建組件「Planner.ViewModel.GroupViewModel」,因爲它有依賴 得到滿足。 「Planner.ViewModel.GroupViewModel」正在等待以下依賴性:
- 服務「Planner.Models.Group」這是未註冊。
我明白這一點例外 - 溫莎城堡是負責構建我的視圖模型,但它沒有處理我的實體的方式。
我已經做了大量的谷歌搜索,但發現很少的答案或建議這個問題,這讓我覺得我所做的是錯誤的。 This Stack Overflow question有兩個答案,這表明在視圖模型上有一個實體是好的,但我開始懷疑這是否屬實。其他問題,such as this one表明該實體應該遠離視圖模型。
解決此問題的正確方法是什麼?
更新:按照要求,這是異常的堆棧跟蹤:
at Castle.MicroKernel.Handlers.DefaultHandler.AssertNotWaitingForDependency()
at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden)
at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired)
at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context)
at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy)
at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
at Castle.MicroKernel.DefaultKernel.Resolve(Type service, IDictionary arguments)
at Castle.Windsor.WindsorContainer.Resolve(Type service)
at Planner.ViewModel.ViewModelResolver.Resolve(String viewModelName) in D:\Planner\Planner\Planner\ViewModel\ViewModelResolver.cs:line 27
at Planner.ViewModel.ViewModelLocator.get_Item(String viewModelName) in D:\Planner\Planner\Planner\ViewModel\ViewModelLocator.cs:line 21
我認爲這是因爲下面的代碼正確的行爲,這(我相信)攔截任何調用構造函數視圖模型,並適當注入它們。
public class ViewModelResolver : IViewModelResolver
{
private IWindsorContainer _container;
public object Resolve(string viewModelName)
{
if (_container == null)
{
_container = new WindsorContainer();
_container.Install(new WindsorViewsInstaller());
_container.Install(new WindsorRepositoriesInstaller());
}
var viewModelType =
GetType()
.Assembly
.GetTypes()
.Where(t => t.Name.Equals(viewModelName))
.FirstOrDefault();
return _container.Resolve(viewModelType);
}
}
更新2:我覺得這回答Ritch的查詢:
public class ViewModelLocator : DynamicObject
{
public IViewModelResolver Resolver { get; set; }
public ViewModelLocator()
{
Resolver = new ViewModelResolver();
}
public object this[string viewModelName]
{
get
{
return Resolver.Resolve(viewModelName);
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = this[binder.Name];
return true;
}
}
我想我現在明白這一點了。問題實際上並不是我發佈的原始代碼。問題是發生實際設置溫莎不是嗎?我仍然不確定我是如何解決這個問題的。
通讀您的示例,我沒有看到您要求Castle Windsor創建GroupViewModel的位置。在示例代碼中,您直接調用構造函數,而不涉及Castle Windsor。你能顯示異常的堆棧跟蹤嗎? – phoog 2012-07-18 19:09:23
容器如何綁定到您創建的GroupViewModel? – 2012-07-18 19:44:50
@RitchMelton我已經用我認爲可以回答你的問題的代碼更新了這個問題。我還用一些新的見解對它進行了更新。 – Stu 2012-07-18 19:51:49