Automapper map from one object to nested objects
Asked Answered
L

3

10

What is the best way to map inner objects with Automapper 2.0

  1. Use the solution in this question (Automapper 1.0)

  2. Create a Custom Value Resolvers

  3. ?

    public class DTOObject
    {
        // MainObject
        public int Id { get; set; }
        public string Name { get; set; }
    
        // SubObject (TopObject)
        public string TopText { get; set; }
        public string TopFont { get; set; }
    
        // SubObject (BottomObject)
        public string BottomText { get; set; }
        public string BottomFont { get; set; }
    }
    
    public class MainObject
    {
        public int Id { get; set; }
        public string Name { get; set; }
    
        public SubObject TopObject { get; set; }
        public SubObject BottomObject { get; set; }
    }
    
    public class SubObject
    {
        public string SubPropText { get; set; }
        public string SubPropFont { get; set; }
    }
    

Custom Value Resolvers

    public class CustomResolver : ValueResolver<DTOObject, SubObject>
    {
        protected override SubObject ResolveCore(DTOObject source)
        {
            return Mapper.Map<DTOObject, SubObject>(source);
        }
    }
Lotte answered 2/2, 2012 at 10:34 Comment(7)
Do you have control of the design of the DTOObject?Chintz
Yes, and no this is a old data base that is in heavy use.Culver
Which direction are you trying to go, DTOObject to MainObject or MainObject to DTOObject?Chintz
Probably best to use Mapper.CreateMap<DTOObject, MainObject>().ForMember(d => d.TopObject, mc => mc.MapFrom(s => new SubObject(){ SubPropText = s.TopText, SubPropFont = s.TopFont } ));Chintz
Also note, in your CustomResolver you shouldn't call Mapper.Map() you should create the SubObject using the properties from the source and return that.Chintz
why not call a sub mapping that takes in the same source object and returns the SubObject I need?Culver
let us continue this discussion in chatCulver
S
14

For me it was possible to use just MapFrom (without ResolveUsing what gives you a chance to use this mapping with IQueryable extensions). So you will get the following in the Automapper configuration:

Mapper.CreateMap<DTOObject, SubObject>()
    .ForMember(dest => dest.SubPropText, opt => opt.MapFrom(x => x.BottomText))
    .ForMember(dest => dest.SubPropFont, opt => opt.MapFrom(x => x.BottomFont));

Mapper.CreateMap<DTOObject, MainObject>()
    .ForMember(dest => dest.TopPart, opt => opt.MapFrom(x => x))
    .ForMember(dest => dest.BottomPart, opt => opt.MapFrom(x => x));
Spadework answered 9/11, 2015 at 1:28 Comment(0)
L
3

I ended up creating my own value resolvers for any SubObjects of MainObject that come from DTOObject.

public class PartResolver<T> : ValueResolver<DTOObject, T>
{
    protected override T ResolveCore(DTOObject source)
    {
        return Mapper.Map<T>(source);
    }
}

Then in my Automapper config I create a map from the DTOObject to SubObject and use the ValueResolver to map that object into the MainObject

Mapper.CreateMap<DTOObject, SubObject>();

Mapper.CreateMap<DTOObject, MainObject>()
    .ForMember(dest => dest.TopPart, opt => opt.ResolveUsing<PartResolver<SubObject>>())
    .ForMember(dest => dest.BottomPart, opt => opt.ResolveUsing<PartResolver<SubObject>>());
Lotte answered 17/2, 2012 at 11:52 Comment(0)
D
1

ResolveUsing is not available with latest version of AutoMapper. So only option left is to use MapFrom. (use @ZedRoth solution).

Disfrock answered 2/2, 2021 at 16:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.