将包装的集合映射到列表

时间:2018-07-19 07:51:49

标签: c# automapper

对于Web API,通常将集合包装在一个(未命名的)对象中,通常带有其他字段。

// GET http://api.example.com/foos/all
{
  "success": true,
  "count": 3,
  "foos": [
    { id: "foo1" },
    { id: "foo2" },
    { id: "foo3" }
  ]
}

在使用Json.NET的C#中,这将映射到以下内容:

class FooData {
    public string Id { get; set; }
}

class FooDataWrapper {
    public bool Success { get; set; }
    public int Count { get; set; }
    public FooData[] Foos { get; set; }
}

... 

var fooData = JsonConvert.DeserializeObject<FooDataWrapper>("{ ... }");

我不想在其余的代码中传递FooDataWrapper,所以我通常创建一个实体类,该实体类仅包含foos内容,而没有其他字段。

public class Foo { // entity model
    public string Id { get; set; }
}

我现在可以使用AutoMapper将FooDataWrapper的实例映射到Foo的列表吗?

FooDataWrapper fooDataWrapper = JsonConvert.DeserializeObject<FooDataWrapper>("{ ... }");
List<Foo> foos = Mapper.Map<FooDataWrapper, List<Foo>>(fooDataWrapper);

CreateMap将如何工作?

在此示例中,请忽略FooFooData看起来相同。现实世界中通常没有看起来完全像实体对象的DTO对象。

1 个答案:

答案 0 :(得分:1)

这实际上很容易做到,只要你知道怎么做。

您需要创建两个地图:

  1. 一个常规映射,用于将FooData映射到Foo
  2. 一个用于将FooDataWrapper映射到List<Foo>的助手映射

对于助手映射,您必须使用自定义类型转换器,因为您不能使用ForMember来选择整个目标对象。

自定义类型转换器可以是lambda,Mapper.Map(FooData[], List<Foo>)就是这样。

// classic mapping
CreateMap<FooData, Foo>();

// helper mapping
CreateMap<FooDataWrapper, List<Foo>>()
  .ConvertUsing((wrapper, list, context) => context.Mapper.Map(wrapper.Foos, list, context));

您甚至可以从类型转换器内部的包装器对象中获得灵感并使用其他属性。这是一个示例,说明如何使用包装程序的Count属性设置结果列表的初始容量。

CreateMap<FooDataWrapper, List<Foo>>()
  .ConvertUsing((wrapper, list, context) => {
      var destination = list ?? new List<Foo>(capacity: wrapper.Count);
      return context.Mapper.Map(wrapper.Foos, destination, context);
  });