Unflatten по соглашению с automapper

#c# #automapper-10

#c# #automapper-10

Вопрос:

В моем проекте я пытаюсь использовать automapper, чтобы максимально приблизить мои командные объекты к объектам моего домена по соглашению.
Это работает, когда я явно сопоставляю два элемента в профиле сопоставления, но, согласно документации automapper, я думаю, что это также должно работать по соглашению. Я создал dotnetfiddle, чтобы продемонстрировать минимальный случай.

Связанные вопросы заканчиваются тем, что люди явно добавляют сопоставление, но это противоречит тому, для чего создан Automapper, и противоречит документации, нет? Это также не работает с выравниванием, поэтому reversemap — это отвлекающий маневр, я думаю.

Отображение

 public class Mapping: Profile
{
    public Mapping()
    {
        this.CreateMap<CreateSelectionCommand, Selection>();
        // .ForMember(selection => selection.Name, opt => opt.MapFrom(x => x.SelectionName))
        .reverseMap()
    }
}
 

Что я ожидаю от работы

 [Fact]
public void ShouldMapName()
{
    var cmd = new CreateSelectionCommand {SelectionName = "selectionName"};
    var selection = _mapper.Map<Selection>(cmd);

    Assert.Equal(cmd.SelectionName, selection.Name); <== selection.Name == ""
}
 

Классы для контекста

 public class Selection
{
    public string Name { get; set; }
}

public class CreateSelectionCommand
{
    public string SelectionName { get; set; }
}
 

Я неправильно прочитал документы или я что-то упустил?

Ответ №1:

Выравнивание заключается в сопоставлении вложенных «сложных» объектов со свойствами на «более высоком» уровне, т. Е. в вашем случае, если CreateSelectionCommand бы у вас было свойство Selection типа, у которого было Name свойство, оно было бы сопоставлено SelectionName с типом назначения (см. this fiddle ).

Вы можете попробовать использовать префиксы, добавив:

 cfg.RecognizePrefixes("Selection");
 

для вашей конфигурации (см. Эту Скрипку), но я сомневаюсь, что это подходящий вариант для обработки на основе соглашений.

Также кажется, что вы можете добавить пользовательское соглашение об именах, используя ISourceToDestinationNameMapper и AddMemberConfiguration :

 class TypeNamePrefixedSourceToDestinationNameMapper : ISourceToDestinationNameMapper
{
    public MemberInfo GetMatchingMemberInfo(IGetTypeInfoMembers getTypeInfoMembers, TypeDetails typeInfo,
        Type destType,
        Type destMemberType, string nameToSearch)
    {
        return getTypeInfoMembers.GetMemberInfos(typeInfo)
            .FirstOrDefault(mi => mi.Name == destType.Name   nameToSearch);
    }
}

var config = new MapperConfiguration(cfg =>
{
    cfg.AddMemberConfiguration().AddName<TypeNamePrefixedSourceToDestinationNameMapper>();

    // ...
}
 

По крайней мере, это работает в этом простом случае, см. Эту скрипку.

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

1. Хорошее объяснение и предложения. Я посмотрю, как далеко я смогу продвинуться с этим съездом. В противном случае я буду придерживаться явного определения сопоставления

2. @BorisCallens был рад помочь! Также я смог сделать что-то подобное (но выглядящее немного более хакерским), добавив некоторые сопоставления свойств cfg.ForAllMaps .