问题描述
我知道AutoMapper仅仅是两个对象之间进行映射属性。
I know AutoMapper is just to map properties between 2 objects.
Automapper不是重塑这必须在我看来,编程数据。
Automapper is not for reshaping data this must be programmed in my opinion.
我有一个 PeriodDTO.IEnumerable<周期>
需要被重新塑造成 PeriodListViewModel.List< CellViewModel>
。
I have a PeriodDTO.IEnumerable<Period>
which needs to be reshaped into a PeriodListViewModel.List<CellViewModel>
.
每个 CellViewModel
持有列表< RowViewModel>
这是不是1对1的映射不是,我想也许这不应该被映射 - 因为它不可能 -
This is no 1 to 1 mapping not and I guess maybe this should not be mapped - because its not possible -
public class PeriodRequest
{
public IEnumerable<Period> Periods { get; set; }
public IEnumerable<DateTime> Weeks { get; set; }
}
public class PeriodListViewModel
{
public PeriodListViewModel(IEnumerable<Period> periods)
{
CellViewModels = new List<CellViewModel>();
var groupedPeriods = periods.GroupBy(p => p.LessonNumber).OrderBy(p => p.Key).ToList();
foreach (var groupedPeriod in groupedPeriods)
{
var cellViewModel = new CellViewModel();
CellViewModels.Add(cellViewModel);
foreach (var period in groupedPeriod)
{
var rowViewModel = new RowViewModel();
rowViewModel.Content = period.Content;
rowViewModel.SchoolclassCode = period.SchoolclassCode;
rowViewModel.DayName = period.LessonDate.ToShortDateString();
rowViewModel.DayIndex = (int)period.LessonDate.DayOfWeek;
rowViewModel.LessonNumber = period.LessonNumber;
cellViewModel.Rows.Add(rowViewModel);
}
}
}
public List<CellViewModel> CellViewModels { get; set; }
}
public class CellViewModel
{
public CellViewModel()
{
Rows = new List<RowViewModel>();
}
public List<RowViewModel> Rows { get; set; }
}
public class RowViewModel
{
public string DayName { get; set; }
public string SchoolclassCode { get; set; }
public string Content { get; set; }
public int DayIndex { get; set; }
public int LessonNumber { get; set; }
}
public class Period
{
public int PeriodId { get; set; }
public DateTime LessonDate { get; set; }
public int LessonNumber { get; set; }
public string SchoolclassCode { get; set; }
public string Content { get; set; }
public int SchoolyearId { get; set; }
public Schoolyear Schoolyear { get; set; }
...
}
目前的时刻PeriodListViewModel可以很容易地单元测试。 ?我问自己,现在怎么可以AutoMapper使情况更加美好
At the moment the PeriodListViewModel can be easily unit tested. I am asking myself now how can AutoMapper make the situation even better?
推荐答案
虽然你没有一个微不足道的1千万:1从映射的IEnumerable<周期>
到列表< CellViewModel>
,你仍然可以只使用它派生从Automapper一定的价值在地方,你得到的类到类接触,这在你的例子是之间的时间
和 RowViewModel
。
While you don't have a trivial 1:1 Mapping from IEnumerable<Period>
to List<CellViewModel>
, you can still derive some value from Automapper by using it only at the place where you get class-to-class contact, which in your example is between Period
and RowViewModel
.
考虑到这一点,还可以更好地利用LINQ的,并得到一切都在一个扫描动作完成,只要你设置从<$认为需要重新塑造预测C $ C>周期到 RowViewModel
。
With this in mind, you can also make better use of LINQ and get everything done in one sweeping motion, provided you set up the projections that require re-shaping from Period
to RowViewModel
.
下面是一个演示一个控制台的代码示例正是这么做的。请注意,我们使用的解析器类Automapper的概念,通过 ValueResolve< TSource,TDestination>
做重新塑造,我已经增加了一个额外的构造函数 CellViewModel
来接受的IEnumerable< RowViewModel方式>
,这有助于提高我们的声明
Here's a console code example that demonstrates exactly that. Note that we're using Automapper's notion of resolver classes via ValueResolve<TSource,TDestination>
do the re-shaping, and I've added an extra constructor to CellViewModel
to accept an IEnumerable<RowViewModel>
, which helps improve our declarations.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AutoMapper;
namespace GroupingMapping
{
public class PeriodRequest
{
public IEnumerable<Period> Periods { get; set; }
public IEnumerable<DateTime> Weeks { get; set; }
}
public class RowViewModel
{
public string DayName { get; set; }
public string SchoolclassCode { get; set; }
public string Content { get; set; }
public int DayIndex { get; set; }
public int LessonNumber { get; set; }
}
public class Period
{
public int PeriodId { get; set; }
public DateTime LessonDate { get; set; }
public int LessonNumber { get; set; }
public string SchoolclassCode { get; set; }
public string Content { get; set; }
public int SchoolyearId { get; set; }
// No definition provided for Schoolyear
//public Schoolyear Schoolyear { get; set; }
}
public class CellViewModel
{
public CellViewModel()
{
Rows = new List<RowViewModel>();
}
public CellViewModel(IEnumerable<RowViewModel> rowVMSet)
{
Rows = new List<RowViewModel>(rowVMSet);
}
public List<RowViewModel> Rows { get; set; }
}
public class PeriodListViewModelEx
{
public PeriodListViewModelEx(IEnumerable<Period> periods)
{
CellViewModels = new List<CellViewModel>(periods
.GroupBy(p => p.LessonNumber)
.OrderBy(grp => grp.Key)
.Select(grp =>
{
return new CellViewModel(
grp.Select(p => { return Mapper.Map<Period, RowViewModel>(p); }));
}));
}
public List<CellViewModel> CellViewModels { get; set; }
}
class DateTimeToDateNameResolver : ValueResolver<DateTime, string>
{
protected override string ResolveCore(DateTime source)
{
return source.ToShortDateString();
}
}
class DateTimeToDayOfWeekResolver : ValueResolver<DateTime, int>
{
protected override int ResolveCore(DateTime source)
{
return (int)source.DayOfWeek;
}
}
class Program
{
static void Main(string[] args)
{
Mapper.CreateMap<Period, RowViewModel>()
.ForMember(dest => dest.DayName, opt => opt.ResolveUsing<DateTimeToDateNameResolver>().FromMember(src => src.LessonDate))
.ForMember(dest => dest.DayIndex, opt => opt.ResolveUsing<DateTimeToDayOfWeekResolver>().FromMember(src => src.LessonDate));
Period[] periods = new Period[3];
periods[0] = new Period { PeriodId = 1, LessonDate = DateTime.Today.Add(new TimeSpan(1, 0, 0, 0)), LessonNumber = 101, SchoolclassCode = "CS101", Content = "Intro to CS", SchoolyearId = 2013 };
periods[1] = new Period { PeriodId = 2, LessonDate = DateTime.Today.Add(new TimeSpan(2, 0, 0, 0)), LessonNumber = 101, SchoolclassCode = "CS101", Content = "Intro to CS", SchoolyearId = 2013 };
periods[2] = new Period { PeriodId = 3, LessonDate = DateTime.Today.Add(new TimeSpan(1, 0, 0, 0)), LessonNumber = 102, SchoolclassCode = "EN101", Content = "English (I)", SchoolyearId = 2013 };
PeriodListViewModelEx pvModel = new PeriodListViewModelEx(periods);
Console.WriteLine("CellViews: {0}", pvModel.CellViewModels.Count);
foreach (CellViewModel cvm in pvModel.CellViewModels)
{
Console.WriteLine("{0} items in CellViewModel Group", cvm.Rows.Count);
}
Console.WriteLine("Inspecting CellViewModel Rows");
foreach (CellViewModel cvm in pvModel.CellViewModels)
{
foreach (RowViewModel rvm in cvm.Rows)
{
Console.WriteLine(" DayName: {0}", rvm.DayName);
Console.WriteLine(" SchoolclassCode: {0}", rvm.SchoolclassCode);
Console.WriteLine(" Content: {0}", rvm.Content);
Console.WriteLine(" DayIndex: {0}", rvm.DayIndex);
Console.WriteLine(" LessonNumber: {0}", rvm.LessonNumber);
Console.WriteLine(" -");
}
Console.WriteLine("--");
}
Console.ReadKey();
}
}
}
这篇关于应AutoMapper也可以用作重新式样映射工具的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!