MVVM-在ViewModels中使用实体 [英] MVVM - Using entities in ViewModels

查看:50
本文介绍了MVVM-在ViewModels中使用实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的只是从MVVM,IoC和依赖注入开始,我遇到了一个绊脚石,我不知道如何解决,但我确实知道它为什么会发生。

I am really just starting out with MVVM, IoC and Dependency Injection and I've hit a stumbling block that I don't know how to solve but I do understand why it's happening.

我将Castle Windsor用于DI和IoC功能,并将MVVM Light用作WPF应用程序中的MVVM框架。使用本教程让Castle Windsor创建一个 MainPageViewModel ,该 IGroupRepository 注入到构造函数中。我已经在温莎城堡中对此进行了模拟实现。

I am using Castle Windsor for DI and IoC functionality and MVVM Light as my MVVM framework in a WPF application. Using this tutorial I have managed to get Castle Windsor to create a MainPageViewModel that has a IGroupRepository injected into the constructor. I have registered a mock implementation of this in Castle Windsor.

以下是 MainPageViewModel 中唯一的其他代码。

The following is the only other code in the MainPageViewModel class besides the constructor.

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

目的是为每个视图创建一个视图模型存储库中的组。但是,这样做会导致温莎城堡给出以下异常:

The intention is to create a view model for each of the groups in the repository. However, doing this causes Castle Windsor to give the following exception:


无法创建组件'Planner.ViewModel.GroupViewModel',因为它具有依赖
可以满足。
'Planner.ViewModel.GroupViewModel'正在等待以下依赖项:

Can't create component 'Planner.ViewModel.GroupViewModel' as it has dependencies to be satisfied. 'Planner.ViewModel.GroupViewModel' is waiting for the following dependencies:


  • 服务 Planner.Models.Group没有注册。

我知道这个例外情况-温莎城堡负责构建我的视图模型,但是它没有办法处理我的实体。

I understand this exception - Castle Windsor is responsible for constructing my view models but it has no way of handling my entity.

我做了很多谷歌搜索,但发现的答案或建议很少,这让我觉得自己在做什么错误。 此堆栈溢出问题有两个答案,其中建议在视图模型上有一个实体是可以的,但我开始怀疑这是真的。其他问题,例如 ,则表明该实体不应位于查看模型。

I have done plenty of Googling but have found very few answers or suggestions to this problem which makes me think that what I am doing is wrong. This Stack Overflow question has two answers which suggest that having an entity on the view model is ok but I'm beginning to wonder if that's true. Other questions, such as this one suggest that the entity should be nowhere near the view model.

解决此问题的正确方法是什么?

What is the correct way to resolve this problem?

更新:根据要求,这是异常的堆栈跟踪:

Update: As requested, this is the stacktrace for the exception:

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

我认为这是正确的行为,因为以下代码(我认为)拦截了对视图模型的构造函数的任何调用,并酌情注入了它们。

I thought that this was the correct behaviour because of the following code which (I believe) intercepts any calls to the constructor of a view model and injects them as appropriate.

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的查询:

Update 2: I think this answers Ritch's query:

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

我想我现在对此有所了解。问题实际上与我发布的原始代码无关。实际上是在设置Windsor时出现问题,不是吗?我仍然不确定如何解决该问题。

I think I understand this a little more now. The problem isn't actually with the original code I posted. The problem is occurring actually setting up Windsor isn't it? I'm still not sure how I solve that problem though.

推荐答案

里奇的答案引导我朝着正确的方向前进,但我想发表一个单独的答案,以便我可以显示最终的代码,以期对下一个尝试这样做的人有用。

Ritch's answer led me in the right direction but I wanted to post a separate answer so that I can show the code that I ended up with in the hope that it will be useful to the next person trying to do this.

作为Ritch的答案,此堆栈溢出问题此博客文章温莎城堡的主要贡献者之一KrzysztofKoźmic都以我认为正确的方式帮助我解决了这个问题。

As well as Ritch's answer, this Stack Overflow question and this blog post by one of the main contributers to Castle Windsor, Krzysztof Koźmic, all helped me to solve this problem in what I believe is the correct way.

正如里奇所说,我不应该直接为我的视图模型调用构造函数-这就是容器的用途。因此,方法是创建一个类,该类将帮助Windsor创建您的视图模型。这被称为类型化工厂设施。这些类的好处是您实际上不需要实现它们-它们只是接口。这是最终将用于创建视图模型的类的代码:

As Ritch said, I shouldn't have been calling the constructor for my view model directly - that is what the container is there for. So the way to do it is to create a class which will help Windsor to create your view model. This is known as a typed factory facility. The good thing about these classes is that you don't actually need to implement them - they are just interfaces. This is the code for the class that will eventually be used to create the view model:

public interface IGroupViewModelFactory
{
    GroupViewModel Create(Group group);
}

这被注入到将创建<$的视图模型的构造函数中c $ c> GroupViewModel 在我的例子中是 MainWindowViewModel 类。这是该类的代码:

This is injected into the constructor for the view model that will create the GroupViewModel which in my case was the MainWindowViewModel class. Here is the code for that class:

public class MainWindowViewModel : ViewModelBase
{
    private readonly IGroupRepository _repository;
    private readonly IGroupViewModelFactory _groupViewModelFactory;

    public MainWindowViewModel(IGroupRepository repository, IGroupViewModelFactory groupViewModelFactory)
    {
        _repository = repository;
        _groupViewModelFactory = groupViewModelFactory;
    }

    public ObservableCollection<GroupViewModel> Groups
    {
        get
        {
            var groupVms = new ObservableCollection<GroupViewModel>();
            IEnumerable<Group> groups = _repository.GetAllGroups();
            foreach (Group g in groups)
            {
                var vm = _groupViewModelFactory.Create(g);
                groupVms.Add(vm);
            }

            return groupVms;
        }
    }
}

最后一步是注册温莎工厂类,并通过以下代码完成:

The final step is to register the factory class with Windsor and that is done by this piece of code:

_container.AddFacility<TypedFactoryFacility>();

_container.Register(
    Component.For<Group>(),
    Component.For<IGroupViewModelFactory>()
    .AsFactory());

值得注意的是,我之前链接的问题没有组件对于上述代码中的< Group>()行。没有这个,我就无法从温莎获得例外,但是不幸的是,我没有保留细节,也无法再复制它,因此我的应用程序中可能还有其他问题。

It's worth noting that the question I linked to earlier did not have the Component.For<Group>(), line in the above piece of code. Without that I was getting an exception from Windsor but unfortunately I didn't keep the details and I can no longer replicate it so there was probably something else amiss in my application.

通过温莎城堡的魔力,您现在可以从存储库中的实体创建视图模型!

Through the magic of Castle Windsor, you can now create view models from entities in a repository!

这篇关于MVVM-在ViewModels中使用实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆