Automap objects from different language

457 Views Asked by At

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);
1

There are 1 best solutions below

0
On BEST ANSWER

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}
    }
});