对于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
将如何工作?
在此示例中,请忽略Foo
和FooData
看起来相同。现实世界中通常没有看起来完全像实体对象的DTO对象。
答案 0 :(得分:1)
这实际上很容易做到,只要你知道怎么做。
您需要创建两个地图:
FooData
映射到Foo
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);
});