【问题标题】:Map a property to list of object using AutoMapper CreateMap使用 AutoMapper CreateMap 将属性映射到对象列表
【发布时间】:2020-01-08 14:22:45
【问题描述】:

首先,对不起我的英语:)

我正在使用 AutoMapper 在类之间进行映射。

我有如下类的结构。

public class OrderDto {
  int Id { get; set; }
}

public class OrderDtoList {
  OrderDto[] Orders { get; set; }
}

public class Order {
  int Id { get; set; }
}

我的问题是,我想使用 AutoMapping Profile 将 OrderDtoList 对象映射到 List。

public class OrderMappingProfile : Profile {
  public OrderMappingProfile() {
    CreateMap<OrderDto, Order>();
    CreateMap<OrderDtoList, List<Order>(); // <<<<<<<< I cannot figure out this.
  }
}

但我不知道如何编写 CreateMap() 函数。

请帮忙。

【问题讨论】:

  • 您已经在使用 OrderDto 到 Order(或反向)的转换。不过,如果您有必要这样做,您可以使用@Alex Petrescu 的答案来解决。

标签: c# .net-core automapper


【解决方案1】:

您可以创建一个实现 ITypeConverter 的类,并使用ConvertUsing 方法创建映射。

public class OrderDtoListMapper : ITypeConverter<OrderDtoList, List<Order>>
{
    public List<Order> Convert(OrderDtoList source, List<Order> destination, ResolutionContext context)
    {
        return context.Mapper.Map<List<Order>>(source.Orders);
    }
}

然后,您可以像这样创建映射:

public class MapperProfile : Profile
{
    public MapperProfile()
    {
        CreateMap<OrderDto, Order>();
        CreateMap<OrderDtoList, List<Order>>().ConvertUsing<OrderDtoListMapper>();
    }
}

希望这就是你要找的东西!

【讨论】:

  • 感谢您的帮助。这对我来说是工作。我错过了使用ResolutionContext context
  • 您无需遍历集合、映射每个对象并将结果具体化为新列表。如果您将集合映射到另一种集合并且为源元素到目标元素定义了映射器,那么 AutoMapper 开箱即用。
【解决方案2】:

从头开始有点困难,但有可能。您必须创建一个ITypeConverter&lt;,&gt; 并将其应用于转换。

请注意,ConvertUsing() 方法也有一个重载,可以简单地添加一个内联函数,但是您需要访问映射器本身才能调用它以将内部对象映射到所需的结果对象,并且仅可用带有类型转换器接口。

public class OrderMappingProfile : Profile
{
    public OrderMappingProfile()
    {
        CreateMap<OrderDto, Order>();
        CreateMap<OrderDtoList, List<Order>>().ConvertUsing<CustomConverter>();
    }
}

public class CustomConverter : ITypeConverter<OrderDtoList, List<Order>>
{
    public List<Order> Convert(OrderDtoList source, List<Order> destination, ResolutionContext context)
    {
        return context.Mapper.Map<List<Order>>(source.Orders);
    }
}

有了这个,您可以直接从 DTO 创建所需的列表:

public static class Program
{
    public static void Main()
    {
        var config = new MapperConfiguration(cfg => cfg.AddProfile<OrderMappingProfile>());
        var mapper = config.CreateMapper();

        var orderList = new OrderDtoList { Orders = Enumerable.Range(1, 10).Select(i => new OrderDto { Id = i }).ToArray() };
        var orders = mapper.Map<List<Order>>(orderList);
    }
}

正如 Lucian 所提到的,ConvertUsing() 的重载提供了上下文。所以你也可以内联它,而不是使用自己的类:

// Use lambda method
CreateMap<OrderDtoList, List<Order>>()
    .ConvertUsing((source, _, context) => context.Mapper.Map<List<Order>>(source.Orders));

// Use static method
CreateMap<OrderDtoList, List<Order>>().ConvertUsing(ListConverter);

private static List<Order> ListConverter(OrderDtoList source, List<Order> destination, ResolutionContext context)
{
    return context.Mapper.Map<List<Order>>(source.Orders);
}

【讨论】:

  • 其实有一个ConvertUsing lambda 重载接收上下文。
  • @LucianBargaoanu:是的,你是对的。刚刚更新了我的答案。
【解决方案3】:

下面是一个通用的扩展,如果你之前没有使用过扩展请注意GenericExtensions类是静态类

public static class GenericExtensions {
   public static object Map<T>(this T source)
    {
        var fullName = source.GetType().FullName;
        var sourceType = source.GetType();


        var baseType = ObjectContext.GetObjectType(source.GetType());

        var config = new MapperConfiguration(cfg =>
            cfg.CreateMap(sourceType, baseType));




        var mapper = config.CreateMapper();

        var entity = mapper.Map(source, sourceType, baseType);

        return entity;

    }

}

public static List<T> Map<T>(this List<T> original)
{
        var config = new MapperConfiguration(cfg =>
            cfg.CreateMap(typeof(T), typeof(T)));

        var mapper = config.CreateMapper();       
        return original.Select(mapper.Map<T, T>).ToList();
}

用法:

对于单个实体:

var originalObject = new  Order();
originalObject.Id = 4; 
var clonedObject = originalObject.Map();

对于实体列表:

var objectList = db.ORDERS.ToList();
var clonedList = objectList.Map();

希望这会有所帮助!

【讨论】:

  • cloneObject 的类型是什么?我认为它与originalObject 是同一类型。我不想这样。
  • 是的,这是一个通用的扩展方法,所以你可以克隆任何实体,你想要什么?克隆一个列表?
  • 是的,我想要这个。 var dtoObject = new OrderDtoList { Orders = new List&lt;OrderDto&gt;() }; List&lt;Order&gt; list = mapper.Map&lt;List&lt;Order&gt;&gt;(dtoObject); 所以,我想将 OrderDtoList 对象中的 orders 属性转换为 List
  • 我添加了第二种方法 Hakan,使用这两种扩展方法可以轻松克隆任何类型的实体或实体列表。
猜你喜欢
  • 2019-03-30
  • 1970-01-01
  • 2017-04-07
  • 1970-01-01
  • 1970-01-01
  • 2015-08-13
  • 2022-11-16
  • 2019-04-26
  • 1970-01-01
相关资源
最近更新 更多