我已经建立了一个简单的测试用例;这是我的类型:
public class FullCompanyInfo {
public int Id { get; set; }
public string Name { get; set; }
public string Foo { get; set; }
public string Bar { get; set; }
public FullCompanyInfo Parent { get; set; }
}
public class CompanyInChainDTO
{
public int Id { get; set; }
public string Name { get; set; }
public CompanyInChainDTO Parent { get; set; }
}
这是我的映射配置:
cfg.CreateMap<FullCompanyInfo, CompanyInChainDTO>()
.ForMember(dto => dto.Parent, opt =>
{
// Stop recursive parent mapping when name is 33
opt.Condition(comp => {
return comp.Name != "33";
});
});
现在,我将原始对象图设置为映射,映射并显示JSON结果:
FullCompanyInfo comp = new FullCompanyInfo
{ Id = 1, Name = "11", Foo = "Foo1", Bar = "Bar1", Parent = new FullCompanyInfo
{ Id = 2, Name = "22", Foo = "Foo2", Bar = "Bar2", Parent = new FullCompanyInfo
{ Id = 3, Name = "33", Foo = "Foo3", Bar = "Bar3", Parent = new FullCompanyInfo {
Id = 4, Name = "44", Foo = "Foo4", Bar = "Bar4", Parent = null }
}
}
};
CompanyInChainDTO compChain = _mapper.Map<CompanyInChainDTO>(comp);
var jsonResult = JsonConvert.SerializeObject(compChain);
结果是:
{
"Id": 1,
"Name": "11",
"Parent": {
"Id": 2,
"Name": "22",
"Parent": {
"Id": 3,
"Name": "33",
"Parent": null
}
}
}
到目前为止,看起来很好,当Name为33时,Parent的映射停止了.但是,当我在返回comp.Name!=“ 33”;时调试opt.Condition lambda时,我发现AutoMapper传入了原始的FullCompanyInfo对象.这个命令:
Id: 44
Id: 33
Id: 22
Id: 11
因此,它正在访问所有4个对象,即使44个对象从未进入最终映射!就像Automapper完全在浏览对象图,然后在我的Condition返回false时删除属性一样.为什么不先调用11的lambda,依此类推,并且仅在告知其映射成员时才加载FullCompanyInfo子对象?
问题在于,在这些环境不仅仅是内存中的实体,而是需要花费时间和资源才能访问的实体的情况下,AutoMapper将访问不需要的内容,而不仅仅是在Condition告知其不进行操作时停止映射引用的实体.
解决方法:
3个字母:Pre.
不能相信我在此上浪费了很多时间;我需要改用opt.PreCondition(…).当您告诉它不这样做时,它实际上会停止访问源成员.