I have been flattening domain objects into DTOs as shown in the example below:
public class Root
{
public string AParentProperty { get; set; }
public Nested TheNestedClass { get; set; }
}
public class Nested
{
public string ANestedProperty { get; set; }
}
public class Flattened
{
public string AParentProperty { get; set; }
public string ANestedProperty { get; set; }
}
// I put the equivalent of the following in a profile, configured at application start
// as suggested by others:
Mapper.CreateMap<Root, Flattened>()
.ForMember
(
dest => dest.ANestedProperty
, opt => opt.MapFrom(src => src.TheNestedClass.ANestedProperty)
);
// This is in my controller:
Flattened myFlattened = Mapper.Map<Root, Flattened>(myRoot);
I have looked at a number of examples, and so far this seems to be the way to flatten a nested hierarchy. If the child object has a number of properties, however, this approach doesn't save much coding.
I found this example:
but it requires instances of the mapped objects, required by the Map() function, which won't work with a profile as I understand it.
I am new to AutoMapper, so I would like to know if there is a better way to do this.
Not sure if this adds value to the previous solutions, but you could do it as a two-step mapping. Be careful to map in correct order if there are naming conflicts between the parent and child (last wins).
To improve upon another answer, specify
MemberList.Source
for both mappings and set the nested property to be ignored. Validation then passes OK.In the latest version of AutoMapper, there's a naming convention you can use to avoid multiple .ForMember statements.
In your example, if you update your Flattened class to be:
You can avoid the use of the ForMember statement:
Automapper will (by convention) map
Root.TheNestedClass.ANestedProperty
toFlattened.TheNestedClassANestedProperty
in this case. It looks less ugly when you're using real class names, honest!I wrote extension method to solve similar problem:
So in your case it can be used like this:
IgnoreAllNonExisting()
is from here.Though it's not universal solution it should be enough for simple cases.
So,
2 more possible solutions:
An alternative approach would be the below, but it would not pass the
Mapper.AssertConfigurationIsValid()
.