I want to copy data object to data transfer object which is nested with the same type.
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' });
I want to copy data object to DTOData (data transfer object).
My approach
dtoData = (DTOData) data;
But it is throwing exception of type mismatch. How can I achive copying the data object to DTOData object, the main complexity with this is that it has nested self referencing. Please help.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
if you don’t care about performance this could be a solution, serialize and deserialize it to the new type using json and newtonsoft, something like:
dtoData = JsonConvert.DeserializeObject<DTOData>(JsonConvert.SerializeObject(data));
in the case of a list object:
dtoData = JsonConvert.DeserializeObject<List<DTOData>>(JsonConvert.SerializeObject(data));
Method 2
You need to explicitly transform each Data object into a new DTOData object one way or another.
You could for example do this iteratively using a Stack<T>. Something like this:
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;
}
Method 3
You can use LINQ and query the original list to the new list.
List<DTOData> dtoData = data
.Select(x => new DTOData(){Id =x.Id, SomeInfo = x.SomeInfo })
.ToList();
Here’s a console app that shows better.
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
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0