You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在控制器调用PaginatedItemsDto时获取对应子类的Items属性

问题:AutoMapper映射分页子类时Items属性丢失,类型鉴别器能否解决该问题?

后端定义了父类PaginatedItems及两个子类GroupedPaginatedItems、FlatPaginatedItems,各自拥有不同类型的Items属性;前端对应定义了PaginatedItemsDto及子类。控制器调用GetItemsAsync能获取包含正确Items、Skip、Take的子类数据,但通过_mapper.Map<PaginatedItemsDto>(result)映射后,Items属性丢失,仅保留Skip和Take字段。询问如何正确获取对应子类的Items属性,以及typeDiscriminator是否能解决该问题。

相关代码

DataProvider类

returnData = new GroupedPaginatedItems
{
    Items = result,
    Skip = 0,
    Take = result.Count()
};

Controller类

public async Task<PaginatedItemsDto> GetItems()
{
    // 获取到包含正确Items、Skip、Take的子类数据
    result = await _itemService.GetItemsAsync(); 
    // 映射后Items属性丢失,仅保留Skip和Take
    return _mapper.Map<PaginatedItemsDto>(result); 
}

后端类定义

public class PaginatedItems
{
    public int Skip { get; set; }
    public int Take { get; set; }
}

public class GroupedPaginatedItems : PaginatedItems
{
    public Dictionary<string, Dictionary<string, List<Item>>>? Items { get; set; }
}

public class FlatPaginatedItems : PaginatedItems
{
    public IEnumerable<Item>? Items { get; set; }
}

前端Dto定义

// 使用如下typeDiscriminator是否有助于调用对应子类?
[JsonDerivedType(typeof(GroupedPaginatedItemsDto), typeDiscriminator: "GroupedItem")]  
public class PaginatedItemsDto
{
    public int Skip { get; set; }
    public int Take { get; set; }
}

public class FlatPaginatedItemsDto : PaginatedItemsDto
{
    [JsonInclude]
    public List<DetailsDto> Items { get; set; } = new();
}

public class GroupedPaginatedItemsDto : PaginatedItemsDto
{
    [JsonInclude]
    public Dictionary<string, Dictionary<string, List<DetailsDto>>>? Items { get; set; }
}

解决方案

1. 核心原因:AutoMapper默认仅映射父类属性

AutoMapper在映射时,默认只会识别目标类型(此处为PaginatedItemsDto)定义的属性,不会自动处理多态场景下的子类属性。直接映射到父类Dto会丢失子类特有的Items字段。

2. 配置AutoMapper多态映射

需要在AutoMapper的Profile中显式配置子类之间的映射,并添加条件判断以根据源类型选择正确的目标Dto:

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        // 基础父类映射
        CreateMap<PaginatedItems, PaginatedItemsDto>();

        // Grouped子类映射,继承父类映射规则
        CreateMap<GroupedPaginatedItems, GroupedPaginatedItemsDto>()
            .IncludeBase<PaginatedItems, PaginatedItemsDto>();

        // Flat子类映射,继承父类映射规则
        CreateMap<FlatPaginatedItems, FlatPaginatedItemsDto>()
            .IncludeBase<PaginatedItems, PaginatedItemsDto>();

        // 多态映射规则:根据源类型匹配对应Dto子类
        CreateMap<PaginatedItems, PaginatedItemsDto>()
            .Include<GroupedPaginatedItems, GroupedPaginatedItemsDto>()
            .Include<FlatPaginatedItems, FlatPaginatedItemsDto>();
    }
}

3. 修正控制器映射与返回逻辑

控制器需要根据源实例的实际类型,映射到对应的Dto子类,而非直接映射到父类Dto:

public async Task<PaginatedItemsDto> GetItems()
{
    var result = await _itemService.GetItemsAsync(); 

    return result switch
    {
        GroupedPaginatedItems grouped => _mapper.Map<GroupedPaginatedItemsDto>(grouped),
        FlatPaginatedItems flat => _mapper.Map<FlatPaginatedItemsDto>(flat),
        _ => _mapper.Map<PaginatedItemsDto>(result)
    };
}

4. 类型鉴别器(typeDiscriminator)的作用

[JsonDerivedType]特性主要作用于JSON序列化/反序列化阶段:

  • 当控制器返回子类Dto时,序列化器会自动添加类型鉴别字段(如自定义的GroupedItem标识),前端可通过该字段识别并反序列化为对应Dto子类。
  • 它不直接解决AutoMapper的映射丢失问题,但结合上述AutoMapper配置,可完整解决从后端实体到前端Dto的映射+序列化全流程问题。

补充:启用JSON多态序列化支持

若使用System.Text.Json,需手动启用多态序列化(默认关闭):

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.TypeInfoResolverChain.Insert(0, 
            new DefaultJsonTypeInfoResolver
            {
                Modifiers = { typeInfo =>
                {
                    if (typeInfo.Type == typeof(PaginatedItemsDto))
                    {
                        typeInfo.PolymorphismOptions = new JsonPolymorphismOptions
                        {
                            TypeDiscriminatorPropertyName = "itemType", // 自定义鉴别字段名
                            IgnoreUnrecognizedTypeDiscriminators = true
                        };
                    }
                }}
            });
    });

内容的提问来源于stack exchange,提问作者So25

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 06:37:38