Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自动映射覆盖递归类型_C#_.net_Automapper_Automapper 6 - Fatal编程技术网

C# 自动映射覆盖递归类型

C# 自动映射覆盖递归类型,c#,.net,automapper,automapper-6,C#,.net,Automapper,Automapper 6,我有一个Dto,看起来有点像这样: class TypeDto { int Id {get; set;} string Name {get; set;} string DisplayName {get; set;} IEnumerable<TypeDto> Children {get; set;} } 请注意子项/嵌套可枚举项中的名称差异 现在,对于地图,我要做: config.CreateMap<Type1, TypeDto>(

我有一个Dto,看起来有点像这样:

class TypeDto
{    
    int Id {get; set;}
    string Name {get; set;}
    string DisplayName {get; set;}
    IEnumerable<TypeDto> Children {get; set;}
}
请注意
子项
/
嵌套
可枚举项中的名称差异

现在,对于地图,我要做:

config.CreateMap<Type1, TypeDto>();

config.CreateMap<Type2, TypeDto>()
    .ForMember(dest => dest.Children, opts => opts.MapFrom(src => src.Nested));

var dto = _mapper.Map<TypeDto>(type1Instance);

_mapper.Map(type2Instance, dto);
映射以下实例后,结果的字段设置为:

Id = 1,
Name = "root",
DisplayName = "Root",
Children = { TypeDto { Id = 2, Name = null, DisplayName = "Child", Children = null } }
所以孩子的
名字
无效,这不是我想要的。显然,我希望它是
“child”
。我应该如何配置映射程序以获得所需的行为

我无法更改
Type1
Type2
类,它们来自外部API


AutoMapper的版本是6.2.1、.NET Framework 4.5.1。

这是一种可能的解决方案:

config.CreateMap<Type2, TypeDto>()
        .ForMember(dest => dest.Children, opts => opts.Ignore())
        .AfterMap((d,e) => AddNestedChildren(d, e));

private void AddNestedChildren(Type2 type, TypeDto dto)
{
    foreach (var child in type.Nested)
    {
        var childDto = dto.Children.SingleOrDefault(c => c.Id == child.Id);
        // keep old properties
        Mapper.Map(child, childDto);
    }
}
config.CreateMap()
.FormMember(dest=>dest.Children,opts=>opts.Ignore())
.AfterMap((d,e)=>AddNestedChildren(d,e));
私有void AddNestedChildren(Type2类型,TypeDto到dto)
{
foreach(type.Nested中的变量子级)
{
var childDto=dto.Children.SingleOrDefault(c=>c.Id==child.Id);
//保留旧财产
Mapper.Map(child,childDto);
}
}
如注释中所述,集合默认为空。对于您的问题,我可以找到一个解决方案,即使用
AfterMap
手动循环子集合/嵌套集合,找到另一个集合的对应子集合(通过Id或您认为相关的任何其他属性),然后手动映射它


我基本上使用了来自卢西恩·巴加奥努评论的相同想法


AutoMapper.Collection
包解决了我的问题。只需将此语句添加到配置中:

config.AddCollectionMappers();
然后在我的两张地图上定义EqualityComparison:

config.CreateMap<Type1, TypeDto>()
    .EqualityComparison((src, dest) => src.Id == dest.Id);

config.CreateMap<Type2, TypeDto>()
    .EqualityComparison((src, dest) => src.Id == dest.Id)
    .ForMember(dest => dest.Children, opts => opts.MapFrom(src => src.Nested));

现在将递归映射到具有匹配的
Id
的任何集合成员上,将
type2Instance.Nested
中未出现在
dto.Children
集合中的所有项添加到集合中,并映射到
dto.Children
集合中的所有项,但是
type2Instance.Nested
不会。

首先清除集合,请选中AutoMapper.Collection。Check.AutoMapper.Collection解决了这个问题。在所有映射之间通过
Id
添加
EqualityComparison
,可使AutoMapper正确更新集合。你能把这个评论变成一个答案,这样我就可以接受了吗?你可以自己发布答案。不起作用。此外,我认为AutoMapper不会触及映射源中不存在的属性(因此根对象的
名称已填充)。@V0ldek您已经提到,实际上AutoMapper应该抛出一个异常,因为它要求您映射目标类型中的所有属性。查看我编辑过的答案,让我知道这是否对您有帮助。
AutoMapper.Collection
也有类似的功能,所以我去用了它(请参阅基于Lucian Bargaonanu评论的“我的”答案)。谢谢你的解决方案。这个解决方案真的很好很干净。这比我的答案还要简单,谢谢分享。
config.AddCollectionMappers();
config.CreateMap<Type1, TypeDto>()
    .EqualityComparison((src, dest) => src.Id == dest.Id);

config.CreateMap<Type2, TypeDto>()
    .EqualityComparison((src, dest) => src.Id == dest.Id)
    .ForMember(dest => dest.Children, opts => opts.MapFrom(src => src.Nested));
_mapper.Map(type2Instance, dto);