Search code examples
c#automapper

AutoMapper - Flatten the HTTP response to my desired class


I have the model classes that my HTTP response will be deserialized.

public class Contract
{
    public IEnumerable<InnerClass> MyConfig { get; set; }
}

public class InnerClass
{
    public int Id { get; set; }
    public string Value { get; set; }
}

I want to map it to a flatter class

public class MyClass
{
    public int IdWithDifferentName { get; set; }
    public string ValueWithDifferentName { get; set; }
}

My challenge is that the response is an array, so effectively I get IEnumerable<Contract> which I then want to map to an IEnumerable<MyClass>, which should contain all InnerClass values, regardless of which instance of Contract it came from.

What do I need to do in AutoMapper to get this to work?

This is how I call AutoMapper:

var configs = _mapper.Map<IEnumerable<MyClass>>(response);

Solution

  • If you are looking to implement the conversion logic in the AutoMapper mapping profile/rule, you need:

    1. Mapping rule for InnerClass to MyClass.

    2. Mapping rule for Contract to IEnumerable<MyClass>.

    3. Mapping rule for IEnumerable<Contract> to IEnumerable<MyClass>.

    CreateMap<InnerClass, MyClass>()
        .ForMember(dest => dest.IdWithDifferentName, opt => opt.MapFrom(src => src.Id))
        .ForMember(dest => dest.ValueWithDifferentName, opt => opt.MapFrom(src => src.Value));
    
    CreateMap<Contract, IEnumerable<MyClass>>()
        .ConvertUsing((src, dest, context) => context.Mapper.Map<IEnumerable<MyClass>>(src.MyConfig));
    
    CreateMap<IEnumerable<Contract>, IEnumerable<MyClass>>()
        .ConvertUsing((src, dest, context) => src.SelectMany(x => context.Mapper.Map<IEnumerable<MyClass>>(x.MyConfig)));
    

    Reference: Custom Type Converters