【问题标题】:Copy nested Model object to DTO object using c#使用 c# 将嵌套模型对象复制到 DTO 对象
【发布时间】:2020-12-08 13:13:22
【问题描述】:

我想将数据对象复制到同类型嵌套的数据传输对象中。

C#

public class Data
{
    public int Id { get; set; }
    public string SomeInfo { get; set; }
    public virtual ICollection<Data> Data { get; set; }
}

public class DTOData
{
    public int Id { get; set; }
    public string SomeInfo { get; set; }
    public virtual ICollection<DTOData> Data { get; set; }
}

List<Data> data = new List<Data>();
data.Add(new Data(){Id =1, SomeInfo  = 'sometext' });

List<DTOData> dtoData = new List<DTOData>();
dtoData.Add(new DTOData(){Id =10, SomeInfo  = 'sometext2' });

我想将数据对象复制到 DTOData(数据传输对象)。

我的方法

dtoData = (DTOData) data;

但它会抛出类型不匹配的异常。如何将数据对象复制到 DTOData 对象,主要的复杂性在于它具有嵌套的自引用。请帮忙。

【问题讨论】:

  • 您必须遍历每个对象并手动为每个副本创建一个新对象,分别分配每个属性。
  • vish,它是一个动态对象,我们不知道嵌套对象有多深。嵌套是指数据的收集。那是我的问题。
  • 那么你也可以让 DTO 数据动态化

标签: c# asp.net asp.net-mvc entity-framework


【解决方案1】:

如果您不关心性能,这可能是一个解决方案,使用 json 和 newtonsoft 将其序列化和反序列化为新类型,例如:

dtoData  = JsonConvert.DeserializeObject<DTOData>(JsonConvert.SerializeObject(data));

在列表对象的情况下:

dtoData  = JsonConvert.DeserializeObject<List<DTOData>>(JsonConvert.SerializeObject(data));

【讨论】:

  • 它会影响性能。性能很慢。
  • @Pearl 是的先生,这是我说的第一件事,这仅适用于低性能不是问题的场景。
  • @Pearl 你可以尝试使用反射,这里有一篇很好的文章:pluralsight.com/guides/…
【解决方案2】:

您需要以一种或另一种方式将每个Data 对象显式转换为新的DTOData 对象。

例如,您可以使用Stack&lt;T&gt; 反复执行此操作。像这样的:

static List<DTOData> Map(List<Data> data)
{
    if (data == null)
        return null;

    var dtos = new List<DTOData>(data.Count);
    var stack = new Stack<(Data source, DTOData parent)>();
    foreach (var root in data)
    {
        //store the root nodes in the list to be returned
        var dto = new DTOData() { Id = root.Id, SomeInfo = root.SomeInfo };
        dtos.Add(dto);

        if (root.Data != null)
        {
            dto.Data = new List<DTOData>(root.Data.Count);
            foreach (var child in root.Data)
                stack.Push((child, dto));
        }

        //handle the child nodes
        while (stack.Count > 0)
        {
            var x = stack.Pop();
            dto = new DTOData() { Id = x.source.Id, SomeInfo = x.source.SomeInfo };

            if (x.parent != null)
                x.parent.Data.Add(dto);

            if (x.source.Data != null)
            {
                dto.Data = new List<DTOData>(x.source.Data.Count);
                foreach (var child in x.source.Data)
                    stack.Push((child, dto));
            }
        }
    }
    return dtos;
}

【讨论】:

    【解决方案3】:

    您可以使用 LINQ 并将原始列表查询到新列表。

    List<DTOData> dtoData = data
        .Select(x => new DTOData(){Id =x.Id, SomeInfo  = x.SomeInfo })
        .ToList();
    

    这是一个显示效果更好的控制台应用程序。

    using SelectMany;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    var listOfAs = new List<A>
    {
        new (new B[] { new (1, 2), new (3, 4) }),
        new (new B[] { new (5, 6), new (7, 8) })
    };
    
    var listOfDtos = listOfAs
        .SelectMany(a => a.Bs)
        .Select(b => new Dto(b.BCount1 + b.BCount2))
        .ToList();
    
    foreach (var dto in listOfDtos) Console.WriteLine(dto.TotalCount);
    
    namespace SelectMany
    {
        public record A(IEnumerable<B> Bs);
        public record B(int BCount1, int BCount2);
        public record Dto(int TotalCount);
    }
    
    //output:
    //3
    //7
    //11
    //15
    

    【讨论】:

    • 是的,如何迭代n级嵌套数据列表?
    • 对于嵌套类型,您可以这样做,但使用 SelectMany()...
    • @Pearl 我已经更新了答案,希望能有所帮助。
    • 我不确定它是如何被降价的。我错过了这个问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多