Initial Situation:
I have a source and a destination object and both have a collection of Elements
. With Automapper I map the source to the destination object. After that, I add information to properties which are only present on the destination object (ItemName
and ItemNumber
). Additionally, I add information to the property Text
of the objects in the collection AssetElementDto
. After that, I call mapper.Map(source_update, destination);
to update the destination object.
Question:
When I run the code the information of ItemName
and ItemNumber
is preserved after the update. What can I do that also the information of the AssetElementDto
of Text
is preserved?
using AutoMapper;
using System.Runtime.InteropServices;
public class Program
{
static void Main(string[] arg)
{
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Source, Destination>().PreserveReferences();
cfg.CreateMap<AssetElement, AssetElementDto>().PreserveReferences();
});
var mapper = new Mapper(config);
var source = new Source()
{
Name = "Sinonis",
Id = new Random().Next(),
Elements = new List<AssetElement>
{
new(){ Id = 1},
new(){ Id = 2}
}
};
var destination = mapper.Map<Destination>(source);
destination.ItemNumber = 42;
destination.Elements.ForEach(e => e.Text ="Wow");
destination.ItemName = "NPC21";
var source_update = new Source()
{
Name = "Nindalf",
Id = new Random().Next(),
Elements = new List<AssetElement>
{
new(){ Id = 3},
new(){ Id = 4}
}
};
Console.WriteLine($"Before update is: {destination.Name} {destination.Id} {destination.ItemNumber} {destination.ItemName}");
destination.Elements.ForEach(e => Console.WriteLine($" {e.Id} {e.Text}"));
mapper.Map(source_update, destination);
Console.WriteLine($"After update is : {destination.Name} {destination.Id} {destination.ItemNumber} {destination.ItemName}");
destination.Elements.ForEach(e => Console.WriteLine($" {e.Id} {e.Text}"));
}
}
#region Source
public class Source
{
public string Name;
public int Id;
public List<AssetElement> Elements;
}
public class AssetElement
{
public int Id;
}
#endregion
#region Destination
public class Destination
{
public string Name;
public int Id;
public List<AssetElementDto> Elements;
public int ItemNumber;
public string ItemName;
}
public class AssetElementDto
{
public string Text;
public int Id;
}
#endregion
Console Output:
Wow
is not preserved after the update.
Before update is: Sinonis 1643275093 42 NPC21
1 Wow
2 Wow
After update is : Nindalf 75522068 42 NPC21
3 null
4 null
CodePudding user response:
Thank you Lucian Bargaoanu for this brief but powerful hint. This solved my problem. Please see the necessary changes in the code below. Here is the link to AutoMapper.Collection.
using AutoMapper;
using AutoMapper.EquivalencyExpression; //add using
public class Program
{
static void Main(string[] arg)
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddCollectionMappers(); //add the collection mapper
cfg.CreateMap<Source, Destination>();
cfg.CreateMap<AssetElement, AssetElementDto>().EqualityComparison((odto, o) => odto.Id == o.Id); //add the equality compersion
});
var mapper = new Mapper(config);
var source = new Source()
{
Name = "Sinonis",
Id = new Random().Next(),
Elements = new List<AssetElement>
{
new(){ Id = 1},
new(){ Id = 2}
}
};
var destination = mapper.Map<Destination>(source);
destination.ItemNumber = 42;
destination.ItemName = "NPC21";
destination.Elements.ForEach(e => e.Text ="Wow");
var source_update = new Source()
{
Name = "Nindalf",
Id = new Random().Next(),
Elements = new List<AssetElement>
{
new(){ Id = 1},//ID's need to be the same as before
new(){ Id = 2}
}
};
Console.WriteLine($"Before update is: {destination.Name} {destination.Id} {destination.ItemNumber} {destination.ItemName}");
destination.Elements.ForEach(e => Console.WriteLine($" {e.Id} {e.Text}"));
mapper.Map(source_update, destination);
Console.WriteLine($"After update is : {destination.Name} {destination.Id} {destination.ItemNumber} {destination.ItemName}");
destination.Elements.ForEach(e => Console.WriteLine($" {e.Id} {e.Text}"));
}
}
#region Source
public class Source
{
public string Name;
public int Id;
public List<AssetElement> Elements;
}
public class AssetElement
{
public int Id;
}
#endregion
#region Destination
public class Destination
{
public string Name;
public int Id;
public List<AssetElementDto> Elements;
public int ItemNumber;
public string ItemName;
}
public class AssetElementDto
{
public string Text;
public int Id;
}
#endregion
Console:
Wow
is preserved in the collection after the update.
Before update is: Sinonis 49772274 42 NPC21
1 Wow
2 Wow
After update is : Nindalf 236466397 42 NPC21
1 Wow
2 Wow