Automapper: непредвиденное поведение отображения с использованием обнуляемого типа - PullRequest
0 голосов
/ 03 мая 2018

В Automapper (6.6.2) я пытаюсь сопоставить логическое значение, допускающее обнуляемость, со свойством объекта назначения (dest.IsEnabled.Value). Но как только исходное значение становится нулевым, все свойство назначения (dest.IsEnabled) становится пустым. Но я только ожидаю, что свойство "value" будет нулевым.

Есть идеи, как это сделать правильно?

class Program
{
    static void Main(string[] args)
    {
        var source = new Source();
        source.IsEnabled = null;

        var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Source, Dest>();
                //.ConstructUsing(ctor => new Dest());
            cfg.CreateMap<bool?, IsEnabledProperty>()
                .ForMember(dst => dst.Value, opt => opt.MapFrom(src => src));
        });

        //var debug = config.BuildExecutionPlan(typeof(Source), typeof(Dest));

        var mapper = config.CreateMapper();

        //var dest = mapper.Map<Source, Dest>(source, new Dest());
        var dest = mapper.Map<Source, Dest>(source);

        if (dest.IsEnabled == null)
        {
            Console.WriteLine("IsEnabled is null. But why? I expect IsEnabled.Value to be null.");
        }

        Console.ReadLine();
    }
}

class Source
{
    public bool? IsEnabled { get; set; }
}

class Dest
{
    public IsEnabledProperty IsEnabled { get; set; } 
        = new IsEnabledProperty() { IsRequired = true };

    // Just to check if the property is initialized
    public OtherProperty OtherProperty { get; set; }
        = new OtherProperty() { IsRequired = true };
}

class IsEnabledProperty
{
    public bool IsRequired { get; set; }
    public bool? Value { get; set; }
}

class OtherProperty
{
    public bool IsRequired { get; set; }
    public bool? Value { get; set; }
}

Обновление

Когда я обновляю отображение следующим образом

cfg.CreateMap<bool?, IsEnabledProperty>()
   .ConvertUsing((src, dst, context) => 
   {
      if (dst != null) 
         dst.Value = src;
      return dst;
   });

dest.IsEnabled.Value отображается правильно для всех вариантов (null, false, true), а также для свойства destination.IsEnabled.IsRequired имеет инициализированное значение true, , но оно вынуждает меня передать экземпляр место назначения для метода отображения : var dest = mapper.Map<Source, Dest>(source, new Dest());. Это не имеет смысла в моих глазах, так как я ожидаю, что объект назначения должен быть сконструирован таким же образом с помощью autopper?

Когда я смотрю на план выполнения, я спрашиваю, почему он проверяет наличие (dest == null) в строке 11, а не просто использует инициализированный typeMapDestination:

(src, dest, ctxt) =>
{
    Dest typeMapDestination;
    return (src == null)
        ? null
        : {
            typeMapDestination = dest ?? new Dest();
            try
            {
                var resolvedValue = ((src == null) || false) ? null : src.IsEnabled;
                var propertyValue = mappingFunction.Invoke(resolvedValue, (dest == null) ? null : typeMapDestination.IsEnabled, ctxt);
                typeMapDestination.IsEnabled = propertyValue;
            }
            catch (Exception ex)
            {
                throw new AutoMapperMappingException(
                    "Error mapping types.",
                    ex,
                    AutoMapper.TypePair,
                    TypeMap,
                    PropertyMap);
            };

            return typeMapDestination;
        };
}

1 Ответ

0 голосов
/ 03 мая 2018

Я думаю, что вы хотите отобразить целое bool? вместо только значения dest.IsEnabled.Value. Таким образом, вы можете спросить логическое значение, имеет ли оно значение с dest.HasValue, и использовать значение с dest.Value.

Возможно, вы захотите добавить AllowNullableMapping в конфигурацию Automapper.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...