我真的在努力实现这个目标,我基本上是在尝试为我的索引视图提供一个ClubViewModel列表,但为了做到这一点,我需要匹配我的Club列表.我正在使用AutoMapper,除了CalendarEntry之外,一切都运行良好,这是我数据库模型中的List和视图模型中的flattened类.
我真的不想改变我的视图模型,因为我按照我想要的方式创建了视图(每天都有bool和相关的开始/结束时间).
首先,这里是成功映射大部分类的控制器:
public ActionResult Index()
{
var clubsList = _service.GetAllClubs();
IList<ClubViewModel> clubsViewModelList = new List<ClubViewModel>();
foreach (var item in clubsList)
{
clubsViewModelList.Add(AutoMapper.Mapper.Map<ClubViewModel>(item));
}
return View(clubsViewModelList);
}
这是我的存储库模型和枚举以及我的Web ViewModel
public class Club
{
public int ClubId { get; set; }
public string Organisation { get; set; }
public List<CalendarEntry> MeetingDays { get; set; }
}
public class CalendarEntry
{
public int CalendarEntryId { get; set; }
public int ClubId { get; set; }
public Days Day { get; set; }
public DateTime From { get; set; }
public DateTime To { get; set; }
}
public enum Days
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
public class ClubViewModel
{
public int ClubId { get; set; }
public string Organisation { get; set; }
public CalendarEntryViewModel CalendarEntryViewModel { get; set; }
}
public class CalendarEntryViewModel
{
public bool IsMonday { get; set; }
public bool IsTuesday { get; set; }
public bool IsWednesday { get; set; }
public bool IsThursday { get; set; }
public bool IsFriday { get; set; }
public DateTime? MondayFrom { get; set; }
public DateTime? MondayTo { get; set; }
public DateTime? TuesdayFrom { get; set; }
public DateTime? TuesdayTo { get; set; }
public DateTime? WednesdayFrom { get; set; }
public DateTime? WednesdayTo { get; set; }
public DateTime? ThursdayFrom { get; set; }
public DateTime? ThursdayTo { get; set; }
public DateTime? FridayFrom { get; set; }
public DateTime? FridayTo { get; set; }
}
最后这是我的AutoMapper配置方法:
public static void RegisterMappings()
{
Mapper.CreateMap<Club, ClubViewModel>()
.ForMember(dest => dest.CalendarEntryViewModel,
opts => opts.Ignore());
Mapper.CreateMap<CalendarEntry, CalendarEntryViewModel>()
.ForMember(dest => dest.IsMonday, opts => opts.Equals(true))
.ForMember(dest => dest.IsTuesday, opts => opts.Equals(true))
.ForMember(dest => dest.IsWednesday, opts => opts.Equals(true))
.ForMember(dest => dest.IsThursday, opts => opts.Equals(true))
.ForMember(dest => dest.IsFriday, opts => opts.Equals(true))
.ForMember(dest => dest.MondayFrom, opts => opts.Equals(DateTime.Now))
.ForMember(dest => dest.MondayTo, opts => opts.Equals(DateTime.Now))
.ForMember(dest => dest.TuesdayFrom, opts => opts.Equals(DateTime.Now))
.ForMember(dest => dest.TuesdayTo, opts => opts.Equals(DateTime.Now))
.ForMember(dest => dest.WednesdayFrom, opts => opts.Equals(DateTime.Now))
.ForMember(dest => dest.WednesdayTo, opts => opts.Equals(DateTime.Now))
.ForMember(dest => dest.ThursdayFrom, opts => opts.Equals(DateTime.Now))
.ForMember(dest => dest.ThursdayTo, opts => opts.Equals(DateTime.Now))
.ForMember(dest => dest.FridayFrom, opts => opts.Equals(DateTime.Now))
.ForMember(dest => dest.FridayTo, opts => opts.Equals(DateTime.Now));
Mapper.AssertConfigurationIsValid();
}
暂时我只是硬编码bools / dates的值,而我尝试让事情发挥作用.
无论如何,我可以以某种方式将第二个CalendarEntry添加到CalendarEntryViewModel Map到Club到ClubViewModel Map作为额外成员,或者我这样做完全错了?
最佳答案 您应该解压缩CalendarEntryViewModel,以便它更接近地表示您域中的日历条目.你现在正试图把一个列表推到一个扁平的物体上……这会让你以后更加痛苦.
在我谈到之前,我不得不提到:
foreach (var item in clubsList)
{
clubsViewModelList.Add(AutoMapper.Mapper.Map<ClubViewModel>(item));
}
Automapper可以处理列表……所以可以是:
var clubsViewModelList = Mapper.Map<IList<Club>, IList<ClubViewModel>>(clubsList);
解压缩视图模型
我知道这就是你说你不想做的……但是你真的应该这样做.它将使您的域与您的视图之间的映射更加简单.由于许多原因,我只是为了让它们分开,但我认为你并没有通过尝试将这种域模型压缩成单个视图模型而给自己带来任何好处.因此将其解压缩到多个视图模型:
public class ClubViewModel
{
public int ClubId { get; set; }
public string Organisation { get; set; }
public IList<CalendarEntryViewModel> CalendarEntries { get; set; } // <--- a list of them
}
然后你的地图变成:
.ForMember(dest => dest.IsMonday, opt => opt.MapFrom(src => src.Day == Days.Monday))
.ForMember(dest => dest.IsTuesday, opt => opt.MapFrom(src => src.Day == Days.Tuesday))
/* etc... */
然后,删除所有可以为空的日期,并用两个字段表示此条目:
public DateTime? From { get; set; }
public DateTime? To { get; set; }
然后您可以在当天订购它们:
foreach (var club in clubsViewModelList) {
club.CalendarEntries = club.CalendarEntries.OrderBy(x => x.Day).ToList();
}
然后在你的视图中……按顺序渲染它们:
@foreach (var calendarEntry in club.CalendarEntries) {
Day: @calendarEntry.Day.ToString()
From: @calendarEntry.From.ToString("D")
}
..等等.
什么时候创建..你只需要根据需要呈现你的条目:
public class ClubCalendarEntryCreateViewModel {
/* other properties here */
public IList<CalendarEntryViewModel> Days { get; set; }
}
然后在你的控制器中:
viewModel.CalendarEntries = new ClubCalendarEntryCreateViewModel {
Days = new List<CalendarEntryViewModel>() {
new CalendarEntryViewModel {
IsMonday = true
},
new CalendarEntryViewModel {
IsTuesday = true
},
/* etc... */
}
};
然后你只需渲染它们并在POST方法中接受它.您对该方法的映射变为:
club.CalendarEntries = Mapper.Map<IList<CalendarEntryViewModel>, IList<CalendarEntry>>(viewModel.CalendarEntries.Days);
我在这里遗漏了一些(比如你将如何重新构建CalendarEntry域对象)..希望你可以填写空白并理解我的意思.我知道这看起来很多 – 但是你以后会更好.你的映射不会像现在一样成为你的敌人(它们永远不应该是你的敌人),你的代码会变得更加清晰.
我希望这有帮助..它可能不是你想听到的,但它肯定是我会怎么做(或类似,给予更多的要求).