I have the following Dto and entity with a nested sub entity.
public class Dto
{
public string Property { get; set; }
public string SubProperty { get; set; }
}
public class Entity
{
public string Property { get; set; }
public SubEntity Sub { get; set; }
}
public class SubEntity
{
public string SubProperty { get; set; }
}
How can I set up a mapping with AutoMapper that will allow me to update an existing instance of Entity with the values from a Dto.
I’m using Mapper.Map(dto, entity) to update an existing entity but when I try to map Dto.SubProperty to Entity.Sub.SubProperty I get an exception for “must resolve to top-level member. Parameter name: lambdaExpression”.
If I create a mapping from Dto to SubEntity using FromMember then Entity.Sub gets replaced with a new instance of SubEntity but that’s not what I want. I just want it to update the properties of the existing instance of SubEntity on the Sub property of Entity.
How can I achieve this?
I solved it by using a combination of the
ResolveUsing<T>()method and implementingIValueResolverand theConvertUsing<T>()method and implementingITypeConverter<TSource,TDestination>.Some of my mapping scenarios are more complicated than normal including bidirectional mapping and nested classes and nested collections. The above helped me to solve them.
EDIT
As requested, I’ve included an example solution. This example is much simpler than the actual types I was dealing with.
If you run the example, which is using
MapperConfig, you’ll get the following output:The string properties all get updated as one would want them to, but
entity.Subgets replaced with a new instance ofSubEntitywhich is no good for when you are wanting to update entities for an ORM that will be persisted to a database.If you modify
Mainso thatMapperConfig2is used instead, you’ll still have the string properties updated as before, but,entity.substill has the same instance ofSubEntitythat it had before. Running the example withMapperConfig2gives this output:The key difference in
MapperConfig2is thatResolveUsingis used along withMyResolverto preserve the value ofentity.Sub.