Automapper — сопоставление типов сущностей с вложенными моделями представлений

Допустим, у меня есть такой объект EF:

public class Person 
{
    public string Name { get; set; }
    public string Psuedonym { get; set; }
    public bool HasPsuedonym { get; set; }
}

Из этого объекта я хочу сопоставить модель представления, которая выглядит так:

public class PersonViewModel 
{
    public string Name { get; set; }
    public PsuedonymViewModel { get; set; }
}

Который содержит эту другую модель представления:

public class PsuedonymViewModel 
{
    public string Psuedonym { get; set; }
    public bool HasPsuedonym { get; set; }
}

Какие сопоставления мне нужно настроить?

У меня есть общая настройка сопоставления, которая создает следующие сопоставления:

Person > PersonViewModel - memberlist.dest
PersonViewModel > Person - memberlist.source

PsuedonymViewModel > Person - memberlist.dest
Person > PsuedonymViewModel - memberlist.source

Общие сопоставления сопоставляют только свойства, которые присутствуют в источнике или назначении, в зависимости от того, каким образом выполняется сопоставление, поэтому мне не нужно вручную добавлять целую кучу игнорируемых свойств для свойств, которые не совпадают.

Когда у меня есть эта настройка, automapper говорит:

AutoMapper.AutoMapperConfigurationException: The following property on MyApplication.PsuedonymViewModel cannot be mapped: 
    Psuedonym 
Add a custom mapping expression, ignore, add a custom resolver, or modify the destination type MyApplication.PsuedonymViewModel.
Context:
    Mapping to property Psuedonym from System.String to MyApplication.PsuedonymViewModel

Я понимаю это сообщение, так как при попытке сопоставления с PsuedonymViewModel из объекта Person нет сопоставления с string на Psuedonym. Я могу решить это с помощью ручного сопоставления следующим образом:

CreateMap<string, PsuedonymViewModel>()
    .ForMember(x => x.HasPsuedonym, opt => opt.Ignore())
    .ForMember(x => x.Psuedonym, opt => opt.MapFrom(y => y));

Хотя это отображает свойство Psuedonym, я должен игнорировать свойство HasPsuedonym, которое мне не нужно, но поскольку оно отображается из string, мне больше не с чем работать.

Такое ощущение, что я сделал что-то принципиально неправильное здесь, но я не могу понять это, любые мысли очень ценятся.


person dougajmcdonald    schedule 19.09.2017    source источник


Ответы (1)


Поскольку вы используете Person для создания PsuedonymViewModel, а также PersonViewModel, вы должны построить оба сопоставления, а в сопоставлении корневого объекта просто укажите, чтобы построить свойство из одного и того же исходного объекта:

cfg.CreateMap<Person, PsuedonymViewModel>();
cfg.CreateMap<Person, PersonViewModel>()
    .ForMember(x=>x.Psuedonym, m=>m.MapFrom(p=>p));
person ASpirin    schedule 24.09.2017
comment
Это правильно, в конце концов я добавил интерфейс к модели Psuedonym, который я мог использовать для идентификации свойств, которым требуется корневое сопоставление, как вы описываете. - person dougajmcdonald; 25.09.2017