0

I think this is an AutoMapper bug but the issue template they have in GitHub states to post something to SO first.

I want to be able to apply an IValueConverter without worrying about null exceptions.

As an example, I'm using a IValueConverter to apply some logic in multiple mappings:

public class ExampleConverter : IValueConverter<string, string>
{
    public string Convert(string sourceMember, ResolutionContext context)
    {
        if (string.IsNullOrEmpty(sourceMember))
        {
            return string.Empty;
        }

        return sourceMember.ToUpper();
    }
}

If I have the following types I'm mapping to and from:

public class ExampleSource
{
    public ExampleNestedSource1 A { get; set; }
}

public class ExampleNestedSource1
{
    public ExampleNestedSource2 B { get; set; }
}

public class ExampleNestedSource2
{
    public string Input { get; set; }
}

public class ExampleDestination
{
    public string Output { get; set; }
}

I can apply the converter like so:

public class ExampleProfile : Profile
{
    public ExampleProfile()
    {
        this.CreateMap<ExampleSource, ExampleDestination>(MemberList.None)
            .ForMember(dst => dst.Output, opt => opt.ConvertUsing(new ExampleConverter(), src => src.A.B.Input));
    }
}

Using the converter like this however, throws an exception when A or B are null:

mapper.Map<ExampleDestination>(new ExampleSource // Throws null reference
{
    A = new ExampleNestedSource1(),
});
mapper.Map<ExampleDestination>(new ExampleSource()); // Throws null reference

Because opt.ConvertUsing(new ExampleConverter(), src => src.A.B.Input) takes in an expression I can't use null propagating operators like src?.A?.B?.Input.

If I remove the converter and use MapFrom, the problem goes away:

public class ExampleProfile : Profile
{
    public ExampleProfile()
    {
        this.CreateMap<ExampleSource, ExampleDestination>(MemberList.None)
            .ForMember(dst => dst.Output, opt => opt.MapFrom(src => src.A.B.Input));
    }
}

But MapFrom doesn't support IValueConverter it only supports IMemberValueResolver which is less reusable.

Is there a better way to handle this scenario?

If not, I'm thinking AutoMapper should either:

  • Add support for IValueConverter in the MapFrom method.
  • ConvertUsing should not invoke the given converter when the expression doesn't resolve to a property and not throw.
  • ConvertUsing should invoke the given converter with null when the expression doesn't resolve to a property (in the same way that MapFrom) and not throw.
Connel
  • 1,844
  • 4
  • 23
  • 36
  • Everything works as expected. This is a feature request I guess. A PR is welcome, but other that that, you should implement that in your own code. – Lucian Bargaoanu Feb 17 '21 at 16:26
  • Why are expressions treated differently in ConvertUsing and MapFrom? What's the design reasoning there? How can I implement this in my code? What is the workaround? – Connel Feb 17 '21 at 16:35
  • For this use case, you can combine `MapFrom` with a value transformer. – Lucian Bargaoanu Feb 17 '21 at 19:45

0 Answers0