我真的刚刚开始使用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