【问题标题】:AutoMapper from a list to collection grouped by dateAutoMapper 从列表到按日期分组的集合
【发布时间】:2014-12-16 09:25:05
【问题描述】:

我有一个父子源,我希望使用 AutoMapper 将其映射到父日期子目标(例如,目标使用 SortedSet 集合按日期对子数据进行分组。

目的是您可以使用 SortedSet 获取该日期的所有“孩子”。

我目前正在使用 IValueResolver 循环遍历源的子项并单独映射,然后将它们添加到 SortedSet。从下面的代码可以看出,如果日期不存在,这就需要在SortedSet集合中新建一个item。

有没有更好的方法来配置映射?

我知道 AutoMapper 可以映射列表(而不仅仅是单个列表项),但由于需要按日期对目标项进行分组,我不确定是否有更好的解决方案来解决我目前的情况使用。

来源类型

public class ViewModel
{
    public ViewModel()
    {
        Days = new SortedSet<DayViewModel>();
    }

    public SortedSet<DayViewModel> Days { get; set; }
}

public class ModelChild 
{
    public DateTime Started { get; set; }
    public string Description { get; set; }
}

public class ModelParent
{
    public string Name;
    public IList<ModelChild> Children = new List<ModelChild>();
}

目的地类型

public class ChildViewModel 
{
    public DateTime Started { get; set; }
    public string Description { get; set; }
}

public class DayViewModel
{
    public DateTime Date { get; set; }

    public DayViewModel()
    {
        Children = new List<ChildViewModel>();
    }

    public IList<ChildViewModel> Children { get; set; }
}

public class DayComparer : IComparer<DayViewModel>
{
    public int Compare(DayViewModel x, DayViewModel y)
    {
        return x.Date.CompareTo(y.Date);
    }
}

public class ViewModel
{
    public ViewModel()
    {
        Days = new SortedSet<DayViewModel>(new DayComparer());
    }

    public SortedSet<DayViewModel> Days { get; set; }
}

IValueResolver

public class DaysResolver : IValueResolver
{
    public ResolutionResult Resolve(ResolutionResult source)
    {
        var person = (ModelParent)source.Context.SourceValue;
        var vm = (ViewModel)source.Context.DestinationValue;

        foreach (var modelChild in person.Children)
        {
            var file = Mapper.Map<ChildViewModel>(modelChild);
            var day = GetDay(vm, file.Started);
            day.Children.Add(file);
        }
        return source.Ignore();
    }

    private static DayViewModel GetDay(ViewModel model, DateTime key)
    {
        var dayViewModel = model.Days.FirstOrDefault(d => d.Date == key);

        if (dayViewModel == null)
        {
            dayViewModel = new DayViewModel
            {
                Date = key
            };

            model.Days.Add(dayViewModel);
        }
        return dayViewModel;
    }
}

映射

private static void Main(string[] args)
{
    Mapper.CreateMap<ModelChild, ChildViewModel>();

    Mapper.CreateMap<ModelParent, ViewModel>()
        .ForMember(d => d.Days, x => x.ResolveUsing<DaysResolver>());

    Mapper.AssertConfigurationIsValid();
}

【问题讨论】:

    标签: c# automapper


    【解决方案1】:

    我想出的一个选项是将 DayViewModel 查找/创建逻辑移动到用于 ModelChild 和 DayViewModel 之间映射的 ContructUsing 方法中。例如。

    Mapper.CreateMap<ModelChild, DayViewModel>()
        .ConstructUsing(context =>
        {
            var key = ((ModelChild) context.SourceValue).Started;
            var daysCollection = (SortedSet<DayViewModel>) context.Parent.DestinationValue;
    
            var dayViewModel = daysCollection.FirstOrDefault(d => d.Date == key);
    
            if (dayViewModel == null)
            {
                dayViewModel = new DayViewModel
                {
                    Date = key
                };
    
                daysCollection.Add(dayViewModel);
            }
    
            dayViewModel.Children.Add(Mapper.Map<ChildViewModel>(context.SourceValue));
            return dayViewModel;
        })
        .ForAllMembers(d => d.Ignore());
    

    这仍然会再次明确调用 Map,但我愿意接受其他建议

    【讨论】:

    • 作为一个 automapper 新手,很高兴知道ConstructUsing() 带来了极大的灵活性并可以解决这个问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 2021-06-09
    • 2021-03-08
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    相关资源
    最近更新 更多