Отдельные карты вложенных объектов с помощью AutoMapper - PullRequest
0 голосов
/ 03 октября 2019

Я пытаюсь поместить вложенные объекты в плоский DTO. Я не контролирую именование ни DTO, ни бизнес-объектов, поэтому переименование / реструктуризация, к сожалению, не представляется возможным.

Вот пример моего случая:

//Domain Objects
public class Order {
  public decimal Total { get; set; }
  public Customer Customer { get; set; }
}

public class Customer {
  public string Name { get; set; }
  public Address Address { get; set; }
}

public class Address {
    public string Street { get; set; }
    public string City { get; set; }
}



//Dtos
public class OrderCustomerDTO {
    public decimal Total { get; set; }
    public string CustomerName { get; set; }
    public string CustomerStreet { get; set; }
    public string CustomerCity { get; set; }
}


//Mapping profile
public class MapperProfile : AutoMapper.Profile {
    public MapperProfile() {
        CreateMap<Order, OrderCustomerDTO>(MemberList.None)
            .ForMember(dst => dst.Total, opt => opt.MapFrom(src => src.Total));

        CreateMap<Customer, OrderCustomerDTO>(MemberList.None)
            .ForMember(dst => dst.CustomerName, opt => opt.MapFrom(src => src.Name));   

        CreateMap<Address, OrderCustomerDTO>(MemberList.None)
            .ForMember(dst => dst.CustomerStreet, opt => opt.MapFrom(src => src.Street))        
            .ForMember(dst => dst.CustomerCity, opt => opt.MapFrom(src => src.City));
    }
}


//Perform mapping
public void MapOrder(IEnumerable<Order> input) {
    var config = new MapperConfiguration(cfg => {
            cfg.AddProfile<MapperProfile>();
        });
    var mapper = config.CreateMapper();
    var mapped = mapper.Map<IEnumerable<OrderCustomerDTO>>(input);
}

Результатиз этого следует, что заполнен только OrderCustomerDTO.Total, а остальное оставлено в виде нулевых значений.

Я думал что-то вроде связывания карт, поэтому предыдущая карта ссылается на следующую и так далее, ноэто приведет к исключению:

// Invalid map
public class MapperProfile : AutoMapper.Profile {
    public MapperProfile() {
        CreateMap<Order, OrderCustomerDTO>(MemberList.None)
            .ForMember(dst => dst.Total, opt => opt.MapFrom(src => src.Total))
            .ForMember(dst => dst, opt => opt.MapFrom(src => src.Customer));//Load nested type

        CreateMap<Customer, OrderCustomerDTO>(MemberList.None)
            .ForMember(dst => dst.CustomerName, opt => opt.MapFrom(src => src.Name))
            .ForMember(dst => dst, opt => opt.MapFrom(src => src.Address)); //Load nested type

        CreateMap<Address, OrderCustomerDTO>(MemberList.None)
            .ForMember(dst => dst.CustomerStreet, opt => opt.MapFrom(src => src.Street))        
            .ForMember(dst => dst.CustomerCity, opt => opt.MapFrom(src => src.City));
    }
}

Это приведет к созданию исключения, подобного следующему:

Исключение типа 'AutoMapper.AutoMapperConfigurationException' произошло в AutoMapper.dll, но не былообрабатывается в коде пользователя Дополнительная информация: Пользовательская конфигурация для элементов поддерживается только для отдельных элементов верхнего уровня для типа.

Очевидно, что я что-то упускаю из-за этих вложенных отображений. Решение (уродливое) состоит в том, чтобы собрать все это в одну Карту, но это означает, что у меня будет что-то вроде:

// Ugly map
public class MapperProfile : AutoMapper.Profile {
    public MapperProfile() {
        CreateMap<Order, OrderCustomerDTO>(MemberList.None)
            .ForMember(dst => dst.Total, opt => opt.MapFrom(src => src.Total))
            .ForMember(dst => dst.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
            .ForMember(dst => dst.CustomerStreet, opt => opt.MapFrom(src => src.Customer.Address.Street))       
            .ForMember(dst => dst.CustomerCity, opt => opt.MapFrom(src => src.Customer.Address.City));
    }
}

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

Как я могу отделить карты автоматов каждого вложенного объекта в его собственную карту, и при этом сохранить связь между вложенным объектом и верхним ??

1 Ответ

0 голосов
/ 04 октября 2019

Решение найдено. Использование .IncludeMemers () поможет, а затем просто определите Map для каждого типа элемента, который вы включаете. Я не знаю, с какой версии это было реализовано, но я могу подтвердить, что это работает с AM 9

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