Search code examples
c#automapperautomapper-5

Automapper - Assign Ranking in the Destination object


I am having the below source and destination objects:

public class Source
{       
    public string Value1{ get; set; }

}

public class Destination 
{
    public string Value1{ get; set; }
    public int Ranking { get; set; }
}

I am trying to map the collection object of Source to Collection object of destination. My source collection is like this:

var source = new List<Source>();
source.Add(new Source(){ Value1= "test1" });
source.Add(new Source(){ Value1= "test2" });

How can I write the mapper if the Ranking attribute in the destination object should correspond to the item index in the source collection?

I.e. after mapping the destination ranking for the Source with Value1 = "test1" will be 1 and the next one will be 2.


Solution

  • You can do it a few ways but if you want your converter unit testable I would suggest using a class that inherits from ITyperConverter<TSource, TDestination>.

    Convert Class:

    public class SourceToDestinationConverter : ITypeConverter<Source, Destination>
    {
        private int currentRank;
        public SourceToDestinationConverter(int rank)
        {
            currentRank = rank;
        }
    
        public Destination Convert(Source source, Destination destination, ResolutionContext context)
        {
            destination = new Destination
            {
                Value1 = source.Value1,
                Ranking = currentRank
            };
            return destination;
        }
    }
    

    Setting your class to the Mapper Configuration:

    Mapper.Initialize(config =>
    {
            config.CreateMap<Source, Destination>().ConvertUsing<SourceToDestinationConverter>();
    });
    Mapper.AssertConfigurationIsValid();
    

    Calling the method:

    var sources = new List<Source>{
        new Source() { Value1 = "test1" },
        new Source() { Value1 = "test2" }
    };
    
    var destinationsRanked = sources.Select(s => Mapper.Map<Source, Destination>(s, options => options.ConstructServicesUsing(
            type => new SourceToDestinationConverter((source.IndexOf(s) + 1))
    )));
    

    The result ends up being.

    Value1 | Ranking
    test1  | 1
    test2  | 2