AutoMapper — Как сопоставить значение вложенного типа, которое может быть null?

#c# #automapper

#c# #automapper

Вопрос:

Вероятно, это простой ответ, но я только начинаю осваивать AutoMapper.

В любом случае, у меня есть объект домена, подобный этому:

 public class User
{
   public string Name { get; set; }
   public FacebookUser FacebookUser { get; set; }
}
  

И ViewModel, подобный этому:

 public class UserViewModel
{
   public string Name { get; set; }
   public long FacebookUniqueId { get; set; }
}
  

Вот что у меня есть в моей конфигурации AutoMapper:

 Mapper.CreateMap<User,UserViewModel>()
   .ForMember(dest => dest.FacebookUniqueId, opt => opt.MapFrom(src => src.FacebookUser.FacebookUniqueId))
  

Но оно выдает исключение, когда FacebookUser объект равен null, чего и следовало ожидать.

Как мне сообщить AutoMapper:

Сопоставьте UserViewModel.FacebookUniqueId для пользователя.FacebookUser.FacebookUniqueId, за исключением случаев, когда оно равно null, затем используйте 0 .

Есть идеи?

Ответ №1:

 opt => opt.MapFrom(src => src.FacebookUser == null ? 0 : src.FacebookUser.FacebookUniqueId)
  

Блин, если бы я только что проверил, сработала ли первая идея, подумал, что MapFrom метод принимает только выражение, указывающее на свойство, чтобы разрешить его таким образом…

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

1. Оно выдало ошибку object ref на src.FacebookUser.FacebookUniqueId , поскольку src.FacebookUser равно null — не знаю, почему это не сработало для вас. В любом случае, добавление заменителя null сделало свое дело — ура!

2. На самом деле, это все еще выдает ошибку — я думал, это сработало, потому что я выполнил сборку, и моя страница отрисовалась должным образом. Но когда я запустил его в режиме отладки, он снова выдал исключение в той же строке. Думаю, AutoMapper проглатывает исключения. Итак, я думаю, что этот конкретный оператор нуждается в проверке null — но как?

3. теперь это должно сработать. Сначала у меня было это, и я думал, что это не сработает, но, по-видимому, это так. Извините, я не протестировал это сначала.

4. да, это то, что я понял, проверка на нуль старой школы. Я надеялся, что у AutoMapper есть собственный интеллектуальный метод для этого. Ну что ж, это работает. Спасибо.

Ответ №2:

Предоставленный вами код работает в последней версии Automapper. Я немного изучил исходные тексты и нашел следующий код:

 try
{
    var result = _method((TSource)source.Value);

    return source.New(result, MemberType);
}
catch (NullReferenceException)
{
    return source.New(null, MemberType);
}
  

Как вы можете видеть теперь, Automapper улавливает все исключения Null при разрешении цепных сопоставлений. Следующий тест зеленого цвета:

 [TestFixture]
public class AutomapperChainingMappingTest
{
    [Test]
    public void ChainMapping_NullProperty_DefaultValueSet()
    {
        AutoMapper.Mapper.CreateMap<User, UserViewModel>()
                  .ForMember(x => x.FacebookUniqueId, o => o.MapFrom(x => x.FacebookUser.FacebookUniqueId));

        var source = new User();
        var model = AutoMapper.Mapper.Map<UserViewModel>(source);

        Assert.AreEqual(model.FacebookUniqueId, default(long));
    }
}

public class User
{
    public FacebookUser FacebookUser { get; set; }
}

public class UserViewModel
{
    public long FacebookUniqueId { get; set; } 
}

public class FacebookUser
{
    public long? FacebookUniqueId { get; set; }
}