I'm trying to find a way to have a mapping configuration that can map between totally different names from a list.
Our database is in Dutch and scaffolding tooling (like scaffold-dbcontext) keeps the table names for the DTO's. Outside our db related layers we would prefer English nouns.
Say I have the following
Afdeling
Id: int
TypeKode: string
Werkenemers: Persoon[]
Department
Id: int
TypeCode: string
Employees: Person[]
Given I know the following word mapping
Afdeling Department
Kode Code
Werkenemers Employees
Persoon Person
Is it then possible to configure AutoMapper to be able to map as such:
Department department = Mapper.Map<Afdeling, Department>(afdeling);
Yes you can do that. Here is code sample, but note it's just sample. It shows general approach but is not complete and contains some unnecessary things, so make sure you understand what's going on there.
First, custom mapper:
class DictionaryMapper : ISourceToDestinationNameMapper {
public Dictionary<string, string> Map { get; set; }
public MemberInfo GetMatchingMemberInfo(IGetTypeInfoMembers getTypeInfoMembers, TypeDetails typeInfo, Type destType, Type destMemberType, string nameToSearch) {
if (Map == null || !Map.ContainsKey(nameToSearch))
return null;
// map properties using Map dictionary
return typeInfo.DestinationMemberNames
.Where(c => c.Member.Name == Map[nameToSearch])
.Select(c => c.Member)
.FirstOrDefault();
}
}
Then
var langMappings = new Dictionary<string, string>();
// note that it's better to use two dictionaries - one for type names
// and another for properties
langMappings.Add("Afdeling", "Department");
langMappings.Add("TypeKode", "TypeCode");
langMappings.Add("Werkenemers", "Employees");
langMappings.Add("Persoon", "Person");
// create reverse map
foreach (var kv in langMappings.ToArray())
langMappings.Add(kv.Value, kv.Key);
var config = new MapperConfiguration(cfg => {
// this will allow mapping type with name from dictionary key above
// to another type indicated with name indicated by value
// so, Afdeling to Department
cfg.AddConditionalObjectMapper().Where((s, d) => langMappings.ContainsKey(s.Name) && langMappings[s.Name] == d.Name);
cfg.AddMemberConfiguration()
// this is default automapper configuration,
// see http://docs.automapper.org/en/stable/Conventions.html
.AddMember<NameSplitMember>()
.AddName<PrePostfixName>(_ => _.AddStrings(p => p.Prefixes, "Get"))
// and this one is our custom one
.AddName<DictionaryMapper>(_ => _.Map = langMappings);
});
var mapper = config.CreateMapper();
var result = mapper.Map<Afdeling, Department>(new Afdeling
{
Id = 1,
TypeKode = "code",
Werkenemers = new[] {
new Persoon() {Id = 2}
}
});