Graham
Graham

Reputation: 1517

How to use AfterMap to map properties on collection property

I have two entities and two DTOs. I am mapping the entities to the DTOs. Simplified versions of the DTOs look like:

public class FooDto {
     // Other properties removed for clarity.
     public string Description { get; set; }
     public decimal Total { get; set; }
     public ICollection<BarDto> Bars { get; set; }
}

public class BarDto {
     // Other properties removed for clarity.
     public decimal Total { get; set; }
}

The Foo and Bar classes are:

public class Foo {

     public ICollection<Bar> Bars { get; set; }
}

public class Bar {
    // Unimportant properties
}

The Mapping

I am mapping this in a method as:

public FooDto Map(IMapper mapper, Foo foo) {

        // _fooTotalService and _barTotalService injected elsewhere by DI.

        return mapper.Map<Foo, FooDto>(foo, opt =>
        {
            opt.AfterMap((src, dest) =>
            {
                dest.Total = _fooTotalService.GetTotal(src);
                dest.Bars.Total = ?????? // Needs to use _barTotalService.CalculateTotal(bar)
            });
        });
}

AutoMapper already has mappings configured for Foo to FooDto and Bar to BarDto which are working fine.

I need to update each BarDto in FooDto with a total using a service (the reasons for which are too lengthy to go into - suffice to say it needs to happen this way).

What syntax do I need to use in AfterMap to map each Total property of BarDto using the _barTotalService.CalculateTotal(bar) method, where bar is the Bar in question?

Note that the _barTotalService.CalculateTotal method takes an instance of Bar not BarDto.

Upvotes: 18

Views: 37996

Answers (2)

Mike
Mike

Reputation: 983

You can look into using TypeConverter, those are classes that can have dependency injection in their constructors. So you inject the services there, and use something like ConstructUsing after CreateMap.

Upvotes: 0

Amit Kumar Ghosh
Amit Kumar Ghosh

Reputation: 3726

This should work -

 AutoMapper.Mapper.CreateMap<Foo, FooDto>()
            .AfterMap((src, dest) =>
            {
                dest.Total = 8;//service call here
                for (var i = 0; i < dest.Bars.Count; i++)
                {
                    dest.Bars.ElementAt(i).Total = 9;//service call with src.Bars.ElementAt(i)
                }
            });
AutoMapper.Mapper.CreateMap<Bar, BarDto>();
var t = AutoMapper.Mapper.Map<FooDto>(new Foo
        {
            Bars = new List<Bar> { new Bar { } }
        });

Upvotes: 27

Related Questions