生成时未知数据类型时,将数据对象映射到合适的ViewModel

背景与问题
我有一个WPF应用程序,该应用程序基本上由一组不同的Skill对象组成,其中每个技能都从抽象基类(SkillBase)继承而来.每个技能应具有自己的View和ViewModel以支持编辑特定技能的值.当用户在列表中选择一项技能并按下“编辑”时,应使用注入的技能实例化相应的Edit-ViewModel.

当我只有一个Skill-data对象时,如何选择应该实例化的Edit-ViewModel?可以通过插件系统添加技能,因此我事先不知道技能的类型.

我今天的解决方案(有效)是用一个属性(EditViewModelForAttribute)装饰每个Edit-ViewModel,该属性告诉它应映射到什么数据类型.这是走的路还是有更好的方法呢?我是否在正确的轨道上?

我能想到的其他解决方案是跳过属性并使用Edit-ViewModels的某种命名约定,另一种解决方案是在启动时通过注入的服务(EditService.RegisterEditViewModel)将技能类型注册为Edit-ViewModel类型. (typeof(WalkSkill),typeof(EditWalkSkillViewModel));)

这是我的代码:

“数据层”

public abstract class SkillBase
{
    // Common properties for all skills
}

public class WalkSkill : SkillBase
{
    // Some properties
}

public class RunSkill : SkillBase
{
    // Some properties
}

“ ViewModel层”

public abstract class EditSkillViewModel<T> : ViewModelBase where T : Skill
{
    public abstract T Skill { get; protected set; }
}

[EditViewModelFor(typeof(WalkSkill))] // Attribute telling that this viewmodel should be instantiated when we want to edit a WalkSkill object
public class EditWalkSkillViewModel : EditSkillViewModel<WalkSkill>
{
    public override WalkSkill Skill { get; protected set; }

    public EditWalkSkillViewModel(WalkSkill skill)
    {
        Skill = skill;
    }
}

[EditViewModelFor(typeof(RunSkill))] // Attribute telling that this viewmodel should be instantiated when we want to edit a RunSkill object
public class EditRunSkillViewModel : EditSkillViewModel<RunSkill>
{
    public override RunSkill Skill { get; protected set; }

    public EditRunSkillViewModel(RunSkill skill)
    {
        Skill = skill;
    }
}

要为特定技能找到正确的ViewModel,我有一个扩展方法来搜索具有EditViewModelForAttribute和特定技能类型的应用程序域中的类型:

public static ViewModelBase GetEditSkillViewModel(this Skill skill)
{
    var viewModelType = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                         from type in assembly.GetTypes()
                         where
                             type.IsDefined(typeof(EditViewModelForAttribute)) &&
                             type.GetCustomAttribute<EditViewModelForAttribute>().SkillType == skill.GetType()
                         select type).SingleOrDefault();

    return viewModelType == null ? null : (ViewModelBase)Activator.CreateInstance(viewModelType, skill);
}

如下所示:

var editViewModel = selectedSkill.GetEditSkillViewModel();

解决方法:

对于我来说,当前使用的解决方案看起来不错,只要每个技能只有一个ViewModel.
但是,有一个建议是使用FirstOrDefault而不是SingleOrDefault并将结果缓存在某个位置.搜索所有类型可能很耗时.

上一篇:Elatic Search中mapping的问题


下一篇:NHibernate:映射一对多关系以填充集合而不使用第二类