使用AutoMapper来处理带有构造函数和嵌套列表的类。

huangapple go评论70阅读模式
英文:

Using AutoMapper for classes with constructors and nested lists

问题

I have translated the code-related content as requested:

我有两个实体: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' 没有默认构造函数 (参数 'type')"
我尝试在映射配置文件中使用 ".constructUsing",当它只有一行代码时,它可以工作:

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

但是当我尝试实际映射嵌套列表时,像这样:

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

它再次引发相同的 "没有默认构造函数" 错误。

我做错了什么?是否有可能创建复杂的自定义对象构造规则?

Please note that I've provided a translation of the code-related content only, as requested. If you have any further questions or need assistance with the code, please feel free to ask.

英文:

I have two entities: User, and UserQuota. "User" contains a list of quotas.
I need to map from these classes to DTO objects: UserWebDtoWithQuotas and UserQuotaWebDto, where UserWebDtoWithQuotas would also contain a list of UserQuotaWebDto's.

I tend to use strict constructors when defining classes in my project, so my DTOs look something like this:

public record UserWebDtoWithQuotas
{
    public Guid UserId { get; private init; }
    public string Username { get; private init; }
    public List&lt;UserQuotaWebDto&gt; Quotas { get; private init; }

    public UserWebDtoWithQuotas(Guid userId, string username, List&lt;UserQuotaWebDto&gt; quotas)
    {
        UserId = userId;
        Username = username;
        Quotas = quotas;
    }
}

I tried just defining two mapping rules, like this:

    CreateMap&lt;User, UserWebDtoWithQuotas&gt;();
    CreateMap&lt;UserQuota, UserQuotaWebDto&gt;();

But this throws an error "Type 'Application.Operations.Users.DTOs.UserWebDtoWithQuotas' does not have a default constructor (Parameter 'type')".
I tried to use ".constructUsing" in the mapper profile, and it works when it's just one line of code:

CreateMap&lt;User, UserWebDtoWithQuotas&gt;()
        .ConvertUsing(user =&gt; new UserWebDtoWithQuotas(user.Id, user.Username, new List&lt;UserQuotaWebDto&gt;()));

But then I tried to actually map the nested list somehow, like this:

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

And it throws the same "no default constructor" again.

What am I doing wrong? Is it at all possible to make complex custom rules for constructing objects?

答案1

得分: 1

以下是您提供的代码的翻译部分:

UserQuota.cs

public record UserQuota
{
    public string quotaA { get; set; }
    public string quotaB { get; set; }
}

UserQuotaWebDto.cs

public record UserQuotaWebDto
{
    public string quotaA { get; set; }
    public string quotaB { get; set; }
}

User.cs

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

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

UserWebDtoWithQuotas.cs

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;
    }
}

test controller

[HttpGet("test")]
public void test()
{
    MapperConfiguration configuration = new MapperConfiguration(cfg =>
    {
        // TestA -> TestB
        cfg.CreateMap<UserQuota, UserQuotaWebDto>();
        cfg.CreateMap<User, UserWebDtoWithQuotas>();
    });
    IMapper mapper = configuration.CreateMapper();

    User user1 = new User(Guid.NewGuid(), "Tom", new List<UserQuota>() { new UserQuota() { quotaA = "qA1", quotaB = "qB1" }, new UserQuota() { quotaA = "qA2", quotaB = "qB2" } });
    UserWebDtoWithQuotas user2 = mapper.Map<UserWebDtoWithQuotas>(user1);
    Console.WriteLine("user1:" + JsonConvert.SerializeObject(user1));
    Console.WriteLine("user2:" + JsonConvert.SerializeObject(user2));
}

output
使用AutoMapper来处理带有构造函数和嵌套列表的类。

英文:

You can try the following code.<br>
UserQuota.cs

    public record UserQuota
    {
        public string quotaA { get; set; }
        public string quotaB { get; set; }
    }

UserQuotaWebDto.cs

    public record UserQuotaWebDto
    {
        public string quotaA { get; set; }
        public string quotaB { get; set; }
    }

User.cs

    public record User
    {
        public Guid UserId { get; private init; }
        public string Username { get; private init; }
        public List&lt;UserQuota&gt; Quotas { get; private init; }

        public User(Guid userId, string username, List&lt;UserQuota&gt; quotas)
        {
            UserId = userId;
            Username = username;
            Quotas = quotas;
        }
    }

UserWebDtoWithQuotas.cs

    public record UserWebDtoWithQuotas
    {
        public Guid UserId { get; private init; }
        public string Username { get; private init; }
        public List&lt;UserQuotaWebDto&gt; Quotas { get; private init; }

        public UserWebDtoWithQuotas(Guid userId, string username, List&lt;UserQuotaWebDto&gt; quotas)
        {
            UserId = userId;
            Username = username;
            Quotas = quotas;
        }
    }

test controller

        [HttpGet(&quot;test&quot;)]
        public void test()
        {
            MapperConfiguration configuration = new MapperConfiguration(cfg =&gt;
            {
                // TestA -&gt; TestB
                cfg.CreateMap&lt;UserQuota, UserQuotaWebDto&gt;();
                cfg.CreateMap&lt;User, UserWebDtoWithQuotas&gt;();
            });
            IMapper mapper = configuration.CreateMapper();


            User user1 = new User(Guid.NewGuid(), &quot;Tom&quot;, new List&lt;UserQuota&gt;() { new UserQuota() { quotaA = &quot;qA1&quot;, quotaB = &quot;qB1&quot; }, new UserQuota() { quotaA = &quot;qA2&quot;, quotaB = &quot;qB2&quot; } });
            UserWebDtoWithQuotas user2 = mapper.Map&lt;UserWebDtoWithQuotas&gt;(user1);
            Console.WriteLine(&quot;user1:&quot;+JsonConvert.SerializeObject(user1));
            Console.WriteLine(&quot;user2:&quot;+JsonConvert.SerializeObject(user2));
        }

output<br>
使用AutoMapper来处理带有构造函数和嵌套列表的类。

huangapple
  • 本文由 发表于 2023年5月17日 14:07:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76269003.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定