我的问题类似于this question,只是我需要合并更深层次。
我有两个相同类型的相似对象。我需要将这些合并为最终结果。一个对象填充来自更可靠源的数据,而另一个对象更完整。我的最终结果应包含来自更可靠来源的所有值。但是,如果可靠来源中没有值,则应从更完整的来源填写。
我的对象看起来像这样(简化):
public class Body {
int Id
Client Client
Details Details
}
public class Client {
int Id
Name Name
Address Address
}
public Name {
string FirstName
string LastName
etc...
}
public class Address {
string StreetName
string HouseNumber
etc...
}
public class Details {
Details1 Details1
Details2 Details2
many more classes which contains more nested classes...
}
所以,我发现我可以使用AutoMapper Condition
选项来指定只映射目标类中的空值。
Mapper.CreateMap<Body, Body>()
.ForAllMembers(opt => opt.Condition(dest => dest.DestinationValue == null));
Mapper.Map(completeObject, reliableObject);
但ForAllMembers
仅适用于该类的直接子成员。因此,上述语句仅检查reliableObject
中的Id,Client en Details字段是否为空。它不会检查架构中更深层次的值,例如reliableObject.Client.Address.StreetName
。
为实现这一目标,我必须为我的架构中的每个类配置Condition
选项,这些选项很多,并分别映射它们。
有没有办法告诉AutoMapper将此条件应用于架构的每个级别? AutoMapper甚至是合并这些对象的最佳方式吗?
我使用AutoMapper版本3.2.1。
答案 0 :(得分:1)
在较新版本的AutoMapper中,Profile.AddConditionalMapper()
允许您定义全局约定,但在版本3中,这是不可能的。
然而,你可以做的是制作一个通用方法,例如:
public void MapIfDestinationIsNull<T>()
{
Mapper.CreateMap<T, T>().ForAllMembers(opt => opt.Condition(dest => dest.DestinationValue == null));
}
并用所有类型调用它。同样多行代码,但每一行都更短。
或者,如果你有办法将所有类型都放入一个数组中(例如你有一个单独的程序集,或者它们有某种通用接口/基类),你可以使用反射来调用这个方法所有类型:
foreach (var type in types)
{
GetType().GetMethod("MapIfDestinationIsNull").MakeGenericMethod(type).Invoke(this, new object[] { });
}
我可以给你的最好建议是简单地升级你的AutoMapper,但如果那不可能那么你就不得不采取一些反思。您还可以查看AutoMapper的源代码,看看新版本如何处理这些内容,并简单地模仿它。