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

使用AutoMapper映射含构造函数与嵌套列表的类遇问题求助

问题:AutoMapper映射带私有初始化器的嵌套DTO时提示“无默认构造函数”

我有两个实体类User和UserQuota,其中User包含一个配额列表。需要将这些类映射到DTO对象UserWebDtoWithQuotas和UserQuotaWebDto,UserWebDtoWithQuotas也包含UserQuotaWebDto的列表。

我倾向于使用严格构造函数定义类,DTO代码如下:

public record UserWebDtoWithQuotas
{
    public Guid UserId { get; private init; }
    public string Username { get; private init; }
    public List<UserQuotaWebDto> Quotas { get; private init; }

    public UserWebDtoWithQuotas(Guid userId, string username, List<UserQuotaWebDto> quotas)
    {
        UserId = userId;
        Username = username;
        Quotas = quotas;
    }
}

我尝试定义以下两条映射规则:

CreateMap<User, UserWebDtoWithQuotas>();
CreateMap<UserQuota, UserQuotaWebDto>();

但抛出错误:Type 'Application.Operations.Users.DTOs.UserWebDtoWithQuotas' does not have a default constructor (Parameter 'type')。

我尝试用.ConvertUsing单行代码映射时可以正常工作:

CreateMap<User, UserWebDtoWithQuotas>()
        .ConvertUsing(user => new UserWebDtoWithQuotas(user.Id, user.Username, new List<UserQuotaWebDto>()));

但当我尝试映射嵌套列表,改用带上下文的ConstructUsing时,再次抛出相同的“无默认构造函数”错误:

CreateMap<User, UserWebDtoWithQuotas>()
        .ConstructUsing((user, context) =>
        {
            var quotas = context.Mapper.Map<List<UserQuotaWebDto>>(user.Quotas);
            return new UserWebDtoWithQuotas(user.Id, user.Username, quotas);
        });

请问我哪里出错了?是否可以为对象构造设置复杂的自定义规则?


解决方案

问题根源

使用ConstructUsing的带ResolutionContext重载时,AutoMapper内部仍会尝试验证目标类型是否存在默认构造函数,即使你已经提供了自定义构造逻辑。而ConvertUsing的单行版本之所以能工作,是因为它完全接管了映射流程,跳过了AutoMapper的默认构造检查环节。

解决方法1:改用带上下文的ConvertUsing重载

将ConstructUsing替换为ConvertUsing的带ResolutionContext参数版本,完全自定义映射逻辑,避免触发默认构造检查:

CreateMap<User, UserWebDtoWithQuotas>()
    .ConvertUsing((user, context) =>
    {
        var quotas = context.Mapper.Map<List<UserQuotaWebDto>>(user.Quotas);
        return new UserWebDtoWithQuotas(user.Id, user.Username, quotas);
    });

解决方法2:简化Record定义(推荐)

C#的Record类型支持主构造函数语法,可以省略显式的构造函数和属性初始化代码,AutoMapper能够自动识别并匹配主构造函数的参数(按名称匹配)。修改DTO定义如下:

public record UserWebDtoWithQuotas(Guid UserId, string Username, List<UserQuotaWebDto> Quotas);

此时只需保留基础的映射配置即可正常工作,无需额外的ConstructUsing或ConvertUsing:

CreateMap<User, UserWebDtoWithQuotas>();
CreateMap<UserQuota, UserQuotaWebDto>();

AutoMapper会自动将User.Id映射到UserId、User.Username映射到Username、User.Quotas映射到Quotas,同时正确处理嵌套列表的映射。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 15:17:42