【发布时间】:2013-11-08 10:34:33
【问题描述】:
我继承了一个具有相当新颖的类结构的项目,我需要为第 3 方 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
}
}
}
希望代码不是太难理解,我已经从现实生活场景中简化了很多,但保留了关键的警告。
【问题讨论】:
-
还不够。目前还不清楚你在问什么。它只是一个代码示例和一堆华夫饼。
-
你看过使用
BeforeMap吗?我现在没有时间看这个,但你可以使用BeforeMap,并且在匿名函数声明中,对你正在努力映射的成员显式调用Mapper.Map -
levelnis - 感谢您立即理解我的问题并提供很好的建议。我会看看那个。再次感谢
-
戴夫 - 我已经编辑了我的问题。如果这是一个简单的问题,我会解决它而不是问。无论如何-感谢您的建设性建议:-)
-
您能否将您的帖子限制为一个可回答的问题?发布示例代码和说明目标并不能帮助我们帮助您(也不能让这个问题对来自 Google 的接下来的 100 人有用):-) 谢谢!
标签: c# automapper hierarchy