Как применить AutoMapper ValueConverters к свойствам, которые могут быть нулевыми

#automapper #automapper-10

#automapper #automapper-10

Вопрос:

Я думаю, что это ошибка AutoMapper, но шаблон проблемы, который у них есть в GitHub, гласит, что сначала нужно опубликовать что-то в SO.

Я хочу иметь возможность применять IValueConverter , не беспокоясь о нулевых исключениях.

В качестве примера я использую a IValueConverter для применения некоторой логики в нескольких сопоставлениях:

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

        return sourceMember.ToUpper();
    }
}
 

Если у меня есть следующие типы, я сопоставляю с и из:

 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; }
}
 

Я могу применить конвертер следующим образом:

 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));
    }
}
 

Однако при использовании такого преобразователя возникает исключение, когда A или B равны нулю:

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

Поскольку opt.ConvertUsing(new ExampleConverter(), src => src.A.B.Input) принимает выражение, я не могу использовать операторы распространения null, подобные src?.A?.B?.Input .

Если я удалю конвертер и использую MapFrom , проблема исчезнет:

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

Но MapFrom не поддерживает IValueConverter , он поддерживает только IMemberValueResolver то, что менее пригодно для повторного использования.

Есть ли лучший способ справиться с этим сценарием?

Если нет, я думаю, AutoMapper должен либо:

  • Добавьте поддержку IValueConverter в MapFrom метод.
  • ConvertUsing не следует вызывать данный конвертер, когда выражение не преобразуется в свойство и не выбрасывается.
  • ConvertUsing следует вызывать данный конвертер с null, когда выражение не преобразуется в свойство (таким же образом, что MapFrom ), а не выбрасывать.

Комментарии:

1. Все работает, как ожидалось. Я думаю, это запрос функции. PR приветствуется, но кроме этого, вы должны реализовать это в своем собственном коде.

2. Почему выражения обрабатываются по-разному в ConvertUsing и MapFrom? В чем причина дизайна? Как я могу реализовать это в своем коде? Каков обходной путь?

3. Для этого варианта использования вы можете комбинировать MapFrom с преобразователем значений.