'How to use a value resolver when resolving a ctor parameter

I have an entity which has no property setters but has a parameterized constructor:

public class Unit
{
    public int Id { get; }

    public Player Owner { get; }

    public Unit(int id, Player owner)
    {
        Id = id;
        Owner = owner;
    }
}

I also have a custom value resolver for AutoMapper which finds a player by its Id:

public class UnitOwnerResolver : IValueResolver<UnitDto, Unit, Player>
{
    private readonly IPlayerService m_playerService;

    public UnitOwnerResolver(IPlayerService playerService)
    {
        m_playerService = playerService;
    }

    public Player Resolve(UnitDto source, Unit destination, Player destinationMember, ResolutionContext context)
    {
        return m_playerService.GetPlayer(source.OwnerId);
    }
}

Problem is, I can not create a proper mapping profile for this entity. This is what I'm trying to do:

CreateMap<UnitDto, Unit>()
    .ForCtorParam("id", options => options.MapFrom(unit => unit.Id))
    .ForCtorParam("owner", options => options.MapFrom<UnitOwnerResolver>();

The third line produces an error, as there is no overload for the ICtorParamConfigurationExpression.MapFrom method taking the value resolver:

No overload for method 'MapFrom' takes 0 arguments

I'm expecting it to work like it does with the ForMember method where there IS such overload:

enter image description here

Can someone please suggest how I can create an instance of the entity using AutoMapper, ctor mapping and value resolvers? I can create a factory, of course, but if it is possible, I would like to stick to mapping to preserve a single approach throughout the application.

Thank you.



Solution 1:[1]

You can do it with a little bit of hacking. You'll have to resolve to service yourself using ServiceCtor func that can be accessed via resolution context Options:

config.CreateMap<UnitDto, Unit>()
    .ForCtorParam("id", options => options.MapFrom(unit => unit.OwnerId))
    .ForCtorParam("owner", options => options.MapFrom((unitDto, context) =>
    {
        var playerService = context.Options.ServiceCtor(typeof(IPlayerService)) as IPlayerService;

        return playerService.GetPlayer(unitDto.OwnerId);
    }));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Prolog