Skip to content

MapFrom doesn't resolve constructor parameters that have no matching source property #3159

@spydacarnage

Description

@spydacarnage

Re-opening issue #2745 with additional details.

Source/destination types

public class Source
{
    public string Result { get; }

    public Source(string result)
    {
        Result = result;
    }
}

public class Dest
{
    public string Result{ get; }
    public dynamic Details { get; }

    public Dest(string result, DestInner1 inner1)
    {
        Result = result;
        Details = inner1;
    }
    public Dest(string result, DestInner2 inner2)
    {
        Result = result;
        Details = inner2;
    }

    public class DestInner1
    {
        public int Value { get; }

        public DestInner1(int value)
        {
            Value = value;
        }
    }

    public class DestInner2
    {
        public int Value { get; }

        public DestInner2(int value)
        {
            Value = value;
        }
    }
}

Mapping configuration

protected override MapperConfiguration Configuration { get; } = new MapperConfiguration(config =>
{
    config.CreateMap<Source, Dest>()
        .ForCtorParam("inner2", cfg => cfg.MapFrom(_ => new Dest.DestInner2(100)));
});

Version: 8.1.1

Expected behavior

Destination.Details should contain an instance of DestInner2.

Actual behavior

AutoMapper.AutoMapperConfigurationException: 'Dest does not have a constructor with a parameter named 'inner2'.

Steps to reproduce

public void Should_redirect_value()
{
    var dest = Mapper.Map<Source, Dest>(new Source("Success"));

    dest.ShouldNotBeNull();
}

I have been looking into this issue, and following the comments in #2745, I added a dummy "inner2" parameter to the Source object, which causes MapDestinationPropertyToSource in TypeMapFactory to pass.

However, because Dest has two constructors, one accepting an instance of inner1 and the other inner2, I would need to have both dummy parameters in Source.

Unfortunately, due to the way that constructor mapping is achieved, the first constructor always passes, so it always hits the "cannot find a constructor with parameter 'inner2'" error.

I note that the previous person to report this was asked to submit a PR last August and hasn't done so, so I have looked into it myself. I have a working prototype, but I don't know the codebase anywhere near well enough to know if I'm missing things.

All existing tests still pass, as does the one I have added to Constructor.cs.

Any assistance would be appreciated.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions