AutoMapper引用映射中的映射

4

我很困惑如何完成这个任务,我需要将我的Index视图提供给ClubViewModel列表,但我需要匹配我的Club列表。我正在使用AutoMapper,除了数据库模型中的CalendarEntry部分外,一切都正常,它是一个列表,在我的视图模型中是一个平坦的类。

我不想改变我的视图模型,因为我已经有了我想要的创建视图(每天的布尔值和关联的起始/完成时间)。

首先,这是已经成功映射大部分类的控制器

    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视图模型
   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();
        }

目前,我只是在努力让事情正常运行的同时硬编码了布尔/日期值。

是否有任何方法可以将第二个CalendarEntry添加到CalendarEntryViewModel Map并作为附加成员添加到ClubClubViewModel Map中,还是我完全错了?


我尝试将其添加为其他成员,但出现错误:.ForMember(d => d.CalendarEntryViewModel,     opt => opt.MapFrom(s => Mapper.Map<CalendarEntry,CalendarEntryViewModel>(s))) - JsonStatham
1个回答

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领域对象)...希望您能填补空白并理解我的意思。我知道这似乎是很多工作,但以后您会受益匪浅。您的映射不会像现在这样成为您的敌人(它们永远不应该成为您的敌人),而且您的代码将变得更加清晰。
希望这可以帮助到您..可能不是您想听到的,但这绝对是我会这样做的方式(或类似方式,如果有更多要求)。

感谢您花时间提供更好的方法。我想要避免在这个时候改变我正在使用的ViewModel的主要原因是我已经将Create视图连接并且正在工作,而且目前正在使用来自一个类的所有bools/from/to,CalendarEntryViewModel在这里没有被使用,是否有任何方法可以继续使用这种方法或者我必须根据这些建议的更改重新创建视图?如果不是的话,这肯定必须在一个分支上进行! - JsonStatham
我有点困惑这段代码应该放在哪里:foreach (var club in clubsViewModelList) { club.CalendarEntries = club.CalendarEntries.OrderBy(x => x.Day).ToList(); }还有,我该如何处理修改后的Mapper.CreateMap<CalendarEntry, CalendarEntryViewModel>()? - JsonStatham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接