Reputation: 443
I have the following object structure :
/// <summary>
/// nested message instance provided by a business service
/// </summary>
public class Message
{
public string Subject { get; set; }
public DateTime CreationDate { get; set; }
public List<Message> Messages { get; set; }
}
and I want to map that object to the following object structure :
/// <summary>
/// UI Object used to display a nested message structure
/// </summary>
public class MessageViewModel : ViewModelBase
{
public bool IsSelected { get; set; }
public string Subject { get; set; }
public DateTime CreationDate { get; set; }
public List<MessageViewModel> Messages { get; set; }
}
Is there any mapper that can get the job done easily ?
Upvotes: 4
Views: 1866
Reputation: 1791
I would strongly recommend using Automapper as its very simple and easy to use. In Automapper, fields having the same name get mapped by default and require minimal configuration. The mapping you want to achieve would be done as follows:
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Message, MessageViewModel>();
});
In case of collections, Automapper can map the following, provided a configuration has been defined for their data types:
Since a mapping is already provided for the data types of the Lists in your case, further configuration will not be needed.
In case you want to map fields with different names or you want some basic level validation in the process, you can use the following syntax to define a configuration:
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Message, MessageViewModel>()
.ForMember(destination => destination.SomeDestinationField, map => map.MapFrom(source => source.SomeSourceFieldWithDifferentName))
.ForMember(destination => destination.SomeDestinationField, map => map.MapFrom(source => source.SomeSourceField ?? SomeDefaultValue));
});
We can then use a MapperConfiguration object to initialize a Mapper and perform our mappings as follows:
SourceClass SourceObject = new SourceClass();
// Populate SourceObject with values
var mapper = config.CreateMapper();
DesitnationClass DestinationObject = mapper.Map<DesitnationClass>(SourceObject);
I would recommend going through these docs.
Upvotes: 3
Reputation: 2898
You can use AutoMapper for this. To map some types first you need to create some mappings:
Mapper.Initialize(cfg => cfg
.CreateMap<Message, MessageViewModel>());
This creates a mapping from Message
to MessageViewModel
. By default AutoMapper maps all the properties with the same name. Nested complex properties will also be mapped when there are mappings for their types specified. So in your example the above mapping is enough because nested property type is the same as its parent type and each property of a source type has its corresponding property with the same name in a target type. Collections are mapped to other collections implicitly.
To map a concrete object you can use Mapper.Map
method:
var messageViewModel = Mapper.Map<MessageViewModel>(message);
This is only example for a static mapper but there is also a possibility to create mapper as an object. For more advanced topics you can read the docs: http://docs.automapper.org/en/stable/
Upvotes: 3