AutoMapper引用地图中的地图

时间:2015-02-06 11:00:25

标签: c# automapper

我真的很难实现这一点,我基本上是在尝试为Index视图提供ClubViewModel列表,但为了做到这一点,我需要匹配我的{{1}列表}。我正在使用Club,除了我的数据库模型中的List和我视图模型中的展平类AutoMapper之外,一切都运行良好。

我真的不想改变我的视图模型,因为我按照我想要的方式创建了视图(每天都有bool和相关的开始/结束时间)。

首先,控制器成功映射了大部分类:

CalendarEntry

以下是我的存储库模型枚举以及我的 Web ViewModels

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

最后,我的 AutoMapper 配置方法

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

暂时我只是硬编码bools / dates的值,而我尝试让事情有效。

无论如何,我可以以某种方式将第二个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(); } CalendarEntry地图添加到CalendarEntryViewModelClub地图作为其他成员,还是我完全错了?

1 个答案:

答案 0 :(得分:2)

您应该解压缩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域名对象)..希望你能填补空白并理解我的意思。我知道这看起来很多 - 但是你以后会更好。你的映射不会像现在一样成为你的敌人(它们不应该成为你的敌人),你的代码将变得更加清晰。

我希望有所帮助..它可能不是你想听到的,但它肯定是我会这样做的(或类似的,给出更多的要求)。