使用AutoMapper的嵌套对象的单独映射

问题描述 投票:0回答:1

我正在尝试将嵌套对象放入扁平化的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));
    }
}

很明显,这种方法不会花费很多时间,而且完全不可维护。

如何将每个嵌套对象的自动映射器映射分离到它自己的映射中,并且仍然在嵌套对象和顶部对象之间保持链接?

c# automapper
1个回答
0
投票

已找到解决方案。使用.IncludeMemers()可以解决问题,然后为包含的每种成员类型定义一个Map。我不知道它是从哪个版本实施的,但是我可以确认它适用于AM 9

© www.soinside.com 2019 - 2024. All rights reserved.