我继承了一个具有相当新颖的类结构的项目,我需要为第三方Web服务进行操作。
基本上,源对象的结构为parent->collection->collection member object
(即集合成员具有简单属性和类成员对象 - 示例应该更好地解释它)。 Dto更简单,只是parent->collection
。
问题在于TrackInfoDto
对象(这些形成Dto中的集合成员)必须从TrackDefinition.TrackType
对象获取属性。这是属于源parent.collection
的对象。
我已经尝试了很多方法在AutoMapper中映射这种关系并绘制了一个空白。
我的主要问题是:
为了提供帮助,下面是我迄今为止尝试过的代码示例。
using System;
using System.Collections.Generic;
using AutoMapper;
namespace AutoMapperTest
{
/*
* requires Automapper PM>
* Install-Package AutoMapper -Version 3.0.0
*/
/* source class objects */
public class Track
{
public string Id { get; set; }
public string FileId { get; set; }
public string MediaName { get; set; }
public List<TrackDefinition> TrackDefinitions { get; set; }
public Track()
{
TrackDefinitions = new List<TrackDefinition>();
}
}
public class TrackDefinition
{
public string Id { get; set; }
public string TrackTypeName { get; set; }
public TrackType TrackType { get; set; }
public TrackDefinition()
{
TrackType = new TrackType();
}
}
public class TrackType
{
public int Id { get; set; }
public string FileTag { get; set; }
public string Name { get; set; }
}
/* destination mapped object model */
public class TrackDto
{
public string Id { get; set; }
public string MediaName { get; set; }
public string FileId { get; set; }
public List<TrackInfoDto> TrackInfo { get; set; }
public TrackDto()
{
TrackInfo = new List<TrackInfoDto>();
}
}
public class TrackInfoDto
{
public string FileTag { get; set; }
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
#region setup
// create small test bed of source data
var sourceTracks = new List<Track>();
// add a few tracks (index start 1 loops)
for (int i = 1; i < 4; i++)
{
var newTrack = new Track
{
Id = string.Format("{0}", i),
MediaName = string.Format("media track {0}", i),
FileId = string.Format("file reference {0}", i)
};
for (int j = 1; j < 3; j++)
{
var trackDefinition = new TrackDefinition
{
Id = string.Format("TD Id {0}", i),
TrackTypeName = "a track type",
TrackType =
{
Id = j*i,
FileTag = string.Format("file tag {0}", j*i),
Name = string.Format("name # {0}", j*i)
}
};
newTrack.TrackDefinitions.Add(trackDefinition);
}
sourceTracks.Add(newTrack);
}
#endregion
#region map
// now for the problem - how to map the fact that the hierarchy
// in Track->TrackDefinition->TrackType
// needs to *miss out* the middle object (TrackDefinition) when
// we map down to the Dto's
Mapper.CreateMap<Track, TrackDto>()
.ForMember(x => x.TrackInfo, opt => opt.Ignore());
Mapper.CreateMap<TrackDefinition, TrackInfoDto>()
.ForMember(dest => dest.FileTag, func => func.MapFrom(src => src.TrackType.FileTag));
Mapper.CreateMap<TrackDefinition, TrackInfoDto>()
.ForMember(dest => dest.Name, func => func.MapFrom(src => src.TrackType.Name));
// first thing -make sure no mapping issues
Mapper.AssertConfigurationIsValid();
// i've even tried to see if that would coerce - nope!!
//Mapper.CreateMap<TrackType, TrackInfoDto>();
// map our source objects down to our dtos
var trackDtos = Mapper.Map<ICollection<Track>, ICollection<TrackDto>>(sourceTracks);
// by inspecting the trackDtos members, we SHOULD see the TrackInfoDto as being
// populated, but alas not. This is the missing puzzle piece
#endregion
}
}
}
希望代码不难理解,我已经从现实生活场景中简化了很多,但保留了关键的警告。
答案 0 :(得分:2)
我已经解决了,我正在寻找映射中间对象的错误方法,我只需要ResolveUsing()
它。这是一个单一的变化:
Mapper.CreateMap<Track, TrackDto>()
.ForMember(dest => dest.TrackInfo, func => func
.ResolveUsing(src => src.TrackDefinitions));