I've got classes like this
public class ClassOne
{
public string Id { get; set; }
//...many others properties
}
public class ClassTwo
{
public string Id { get; set; }
//...many others properties differents from classeOne
public string Email { get; set; }
}
public class ClassThree
{
public string Id { get; set; }
//...many others properties differents from classeOne and classTwo
public string Email { get; set; }
}
public class ViewModel
{
//...same properties as classeOne
public string EmailClasseTwo { get; set; }
public string EmailClassThree { get; set; }
}
public class ObjectReturnByLinqQuery
{
public ClassOne classOne { get; set; }
public ClassTwo classTwo { get; set; }
public ClassThree classThree { get; set; }
}
How to create map between the ViewModel
and ObjectReturnByLinqQuery
without doing one by one member for each classes ?
something like
config.CreateMap<ObjectReturnByLinqQuery, ViewModel>()
.ForMember(ViewModel => ViewModel.EmailClasseTwo , ModelDB => ModelDB.MapFrom(src => src.ClasseTwo.Email))
.ForMember(ViewModel => ViewModel.EmailClasseThree , ModelDB => ModelDB.MapFrom(src => src.ClasseThree.Email))
and for all other members take them from src.ClassOne
Unfortunately there is no out of the box way to do that. But you can create a Custom Naming Convention like this:
using AutoMapper;
using AutoMapper.Configuration.Conventions;
using System.Reflection;
class CustomMapMember : IChildMemberConfiguration
{
Dictionary<TypePair, List<PropertyInfo>> map = new Dictionary<TypePair, List<PropertyInfo>>();
public CustomMapMember Add(Type destType, Type sourceType, string sourcePropertyName)
{
var key = new TypePair(sourceType, destType);
if (!map.TryGetValue(key, out var properties))
map.Add(key, properties = new List<PropertyInfo>());
properties.Add(sourceType.GetProperty(sourcePropertyName));
return this;
}
public bool MapDestinationPropertyToSource(ProfileMap options, TypeDetails sourceType, Type destType, Type destMemberType, string nameToSearch, LinkedList<MemberInfo> resolvers, IMemberConfiguration parent)
{
if (map.TryGetValue(new TypePair(sourceType.Type, destType), out var properties))
{
foreach (var property in properties)
{
resolvers.AddLast(property);
var memberType = options.CreateTypeDetails(property.PropertyType);
if (parent.MapDestinationPropertyToSource(options, memberType, destType, destMemberType, nameToSearch, resolvers))
return true;
resolvers.RemoveLast();
}
}
return false;
}
}
and then use it like this:
config.AddMemberConfiguration().AddMember<CustomMapMember>(m =>
// Configure the custom mappings here
m.Add(typeof(ViewModel), typeof(ObjectReturnByLinqQuery), nameof(ObjectReturnByLinqQuery.classOne))
);
config.CreateMap<ObjectReturnByLinqQuery, ViewModel>()
.ForMember(ViewModel => ViewModel.EmailClasseTwo, ModelDB => ModelDB.MapFrom(src => src.classTwo.Email))
.ForMember(ViewModel => ViewModel.EmailClassThree, ModelDB => ModelDB.MapFrom(src => src.classThree.Email));