自动映射器:展平嵌套的集合

时间:2019-12-24 10:06:22

标签: collections automapper flatten

将一个具有集合的DTO映射到实体模型中的扁平化版本时遇到问题。

这里是DTO类:

public class Location {
   public int LocationId {get; set;}
   public string LocationName {get;set;}
   public List<HoursOfOperation> HoursOfOperation {get; set;}
}

public class HoursOfOperation {
      public int WeekNumber {get; set;}
      public int DayNumber {get; set;}
      public List<TimeSlot> OperatingHours {get; set;}
}

public class TimeSlot{
      public TimeSpan StartTime {get; set;}
      public TimeSpan EndTime { get; set;}
}

这是我的实体模型类:

 public partial class HoursOfOperation
    {
        public int HoursOfOperationId { get; set; }
        public int FkLocationId { get; set; }
        public short WeekNumber { get; set; }
        public short DayNumber { get; set; }
        public TimeSpan StartTime { get; set; }
        public TimeSpan EndTime { get; set; }
    }

我已经使用Automapper了,到此为止:

public OpHoursMappingProfile()
    {
        CreateMap<HoursOfOperation, Models.ClientDb.HoursOfOperation>()
            .ForMember(dest => Enum.GetName(typeof(DayOfWeek), dest.DayNumber), opt => opt.MapFrom(t => t.DayNumber))
            .ForMember(dest => dest.WeekNumber, opt => opt.MapFrom(t => t.WeekNumber));
    }

我不确定如何映射时隙。我尝试按照here的说明创建自定义扩展名,但没有帮助。

1 个答案:

答案 0 :(得分:0)

您的评论使我可以更好地了解您要实现的目标,在我看来,它正在将单个源对象映射到目标对象的集合。为此,我建议创建自定义类型转换器:

public class HoursOfOperationConverter : ITypeConverter<HoursOfOperation, IEnumerable<Models.ClientDb.HoursOfOperation>>
{
    public IEnumerable<Models.ClientDb.HoursOfOperation> Convert(
        HoursOfOperation source,
        IEnumerable<Models.ClientDb.HoursOfOperation> destination,
        ResolutionContext context)
    {
        foreach (var timeSlot in source.OperatingHours)
        {
            var hours = context.Mapper.Map<Models.ClientDb.HoursOfOperation>(source);
            hours = context.Mapper.Map(timeSlot, hours);

            yield return hours;
        }
    }
}

请注意,转换器在每次迭代中如何两次映射到HoursOfOperation。从DTO的原始运行时间开始,这是第一次,因此可以填充常规属性,例如FkLocationId。从当前时隙第二次开始,因此StartTimeEndTime日期可以从相应的时隙中填写。了解为什么第二次使用映射到现有对象也很重要。之所以如此,是因为否则第一次映射的结果将会丢失。

映射个人资料:

public class OpHoursMappingProfile : Profile
{
    CreateMap<HoursOfOperation, Models.ClientDb.HoursOfOperation>()
        .ForMember(
            destination => destination.HoursOfOperationId,
            options => options.MapFrom(source => source.Id))
        .ForMember(
            destination => destination.FkLocationId,
            options => options.MapFrom(source => source.LocationId));
    CreateMap<TimeSlot, Models.ClientDb.HoursOfOperation>();
    CreateMap<HoursOfOperation, IEnumerable<Models.ClientDb.HoursOfOperation>>()
        .ConvertUsing<HoursOfOperationConverter>();
}

我不完全了解您的周/日号码映射,因此我将其留给您实施。

用法示例:

var result = mapper.Map<IEnumerable<Models.ClientDb.HoursOfOperation>>(hours);