MVC如何从我的域模型映射到特定的视图模型

时间:2012-06-26 11:32:15

标签: asp.net-mvc viewmodel automapper

我开始使用映射域模型的概念来查看ASP.NET MVC中的模型,之后观看建议将特定的viewModel传递给视图。

我已经能够管理一个域模型到具有较少属性的简单视图模型的基本映射,但现在需要生成更复杂的视图模型并且无法弄清楚它。我有以下域模型

public class Club
{
    public int ClubID { get; set; }
    public string FullName { get; set; }
    public string Description { get; set; }
    public string Telephone { get; set; }
    public string URL { get; set; }
    public DateTime CreatedDate { get; set; }

    public virtual ICollection<Member> Members{ get; set; }
}

public class Member
{
    public int MemberID{ get; set; }
    public string Name { get; set; }
    public MemberType Membership{ get; set; }
    public virtual Club Club { get; set; }
    public virtual int ClubID { get; set; }
}

public enum MemberType
{
    Standard,
    Special,
    Limited
}

我想要映射到这样的视图模型(注意:我已经将它拆分为这样,因为我觉得它很有意义,但我不确定)......

public class ClubDetailsViewModel
{
    public int ClubID { get; set; }
    public string FullName { get; set; }
    public string Description { get; set; }
    public IList<ClubDetailsMemberSummaryViewModel> Members { get; set; }
}

public class ClubDetailsMemberSummaryViewModel
{
    public MemberType Membership { get; set; }
    public int MemberCount { get; set; }
}

我试图最终得到的是一个页面,其中显示了一些俱乐部的详细信息以及俱乐部成员类型的总结报告以及成员数量。如:

Some Club Name
Description of the club.....

CLUB MEMBERS
Limited - 15
Standard - 100

所以我认为viewmodel对此有意义(尽管可能是一种更好的方法)。在我努力的地方是如何映射元素。我可以让俱乐部将主要领域映射到俱乐部视图模型,但实际上无法解决如何将俱乐部列表的结果映射到他们的视图模型,然后将其作为列表添加到主视图模型中。

我使用此

从我的存储库中获取俱乐部
var clubs = _clubRepository.GetClubByID(ID);

然后我可以使用此

转换使用实体框架中的数据访问层中的include返回的Courts
var grpCourts = from c in clubs.Members
                group c by c.Membership into grp 
                select new { st = grp.Key, count = grp.Distinct().Count() };

如何循环生成的记录并将其映射到ClubDetailsMemberSummaryViewModel,然后将其列表添加到主ClubDetailsViewModel?

2 个答案:

答案 0 :(得分:1)

ClubClubDetailsViewModel的映射将是微不足道的,Members除外。对于该属性,您可以编写快速解析器内联或编写自己的自定义解析程序。内联解析器看起来像这样:

Mapper.CreateMap<Club, ClubDetailsViewModel>()
    .ForMember(dest => dest.Members, opt => opt.ResolveUsing(src => 
    {
        return src.Members
            .GroupBy(m => m.Membership)
            .Select(grp => new ClubDetailsMemberSummaryViewModel
            {
                Membership = grp.Key,
                MemberCount = grp.Distinct().Count()
            });
    }));

我认为将更复杂的解析器重构为自己的类是很好的做法:

public class MembershipClubDetailsResolver : ValueResolver<Club, IList<ClubDetailsMemberSummaryViewModel>>
{
    protected override IList<ClubDetailsMemberSummaryViewModel> ResolveCore (Club source) 
    {
        return source.Members
            .GroupBy (m => m.Membership)
            .Select(grp => new ClubDetailsMemberSummaryViewModel
            {
                Membership = grp.Key,
                MemberCount = grp.Distinct().Count()
            })
            .ToList();
    }
}

然后在映射中使用该解析器:

Mapper.CreateMap<Club, ClubDetailsViewModel>()
    .ForMember(dest => dest.Members, opt => opt.ResolveUsing<MembershipClubDetailsResolver>());

答案 1 :(得分:0)

您的映射似乎相当复杂,我想我会使用automapper的.ConvertUsing方法

Mapper.CreateMap<List<Club>,List<ClubDetailsViewModel>>()
.ConvertUsing<ClubToClubDetailsViewModel>();

转换类具有以下继承

public class ClubToClubDetailsViewModel: TypeConverter<List<Club>,List<ClubDetailsViewModel>>
{
....
}

或者你可以修改创建两个“简单”映射

Mapper.CreateMap<Club,ClubDetailsViewModel>()

这将映射除名为Members

的属性之外的所有内容

然后你需要为ClubDetailsMemberSummaryViewModel的成员创建一个映射,你可以手动进行映射,或者你也可以在automapper中配置它。

有关automapper的更多具体细节,您可以访问https://github.com/AutoMapper/AutoMapper/wiki