2013-10-23 13 views
34

Ich verwende Auto Mapper, um mehrere Objekte (db-Klasse in ui Objekte) zuzuordnen.Automapper - Multi-Objekt-Quelle und ein Ziel

Karte 1:

Mapper.CreateMap<sourceone, destination>().ForMember(sss => sss.one, m => m.MapFrom(source => source.abc)); 

Karte 2:

Mapper.CreateMap<sourcetwo, destination>().ForMember(sss => sss.two, m => m.MapFrom(source => source.xyz)); 

destination d = new destination(); 

// Karte 1

d = AutoMapper.Mapper.Map<sourceone, destination>(sourceone); 

// Karte 2

d = AutoMapper.Mapper.Map<sourcetwo, destination>(sourcetwo); 

Sobald ich die 'Map 2' aufgerufen habe, sind die Werte, die mit Map 1 aufgefüllt wurden, verloren. (Date. Destination.one wird leer). Wie behebe ich das?

Antwort

54

Map hat eine Überlastung, die ein Quell- und Zielobjekt nimmt:

d = AutoMapper.Mapper.Map<sourceone, destination>(sourceone); 

/* Pass the created destination to the second map call: */ 
AutoMapper.Mapper.Map<sourcetwo, destination>(sourcetwo, d); 
+1

Ausgezeichnet. Danke – CoolArchTek

+6

Dies ist hässlich und verwirrend, sollte die API eindeutig eine Karte (Params) -Methode – Filip

+1

@Flip: Ich könnte Missverständnis, was Sie meinen, aber es _does_ gehören eine 'Map (params)' Methode, es gibt nur eine zurück neues 'T'. –

4
public class Person 
{ 
    public string Name { get; set; } 
    public string PhNo { get; set; } 
} 
public class Company 
{ 
    public int EmpNo { get; set; } 
    public string Title { get; set; } 
} 

public class PersonCompany 
{ 
    public string Name { get; set; } 
    public string PhNo { get; set; } 

    public int EmpNo { get; set; } 
    public string Title { get; set; } 
} 

//you can test as below 
     var pMap = Mapper.CreateMap<Person,PersonCompany>(); 
     pMap.ForAllMembers(d => d.Ignore()); 
     pMap.ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name)) 
      .ForMember(d => d.PhNo, opt => opt.MapFrom(s => s.PhNo)); 

     var cMap = Mapper.CreateMap<Company, PersonCompany>(); 
     cMap.ForAllMembers(d => d.Ignore()); 
     cMap.ForMember(d => d.EmpNo, opt => opt.MapFrom(s => s.EmpNo)) 
      .ForMember(d => d.Title, opt => opt.MapFrom(s => s.Title)); 


     var person = new Person { Name = "PersonName", PhNo = "212-000-0000" }; 
     var personCompany = Mapper.Map<Person,PersonCompany>(person); 
     var company = new Company { Title = "Associate Director", EmpNo = 10001 }; 
     personCompany = Mapper.Map(company, personCompany); 

     Console.WriteLine("personCompany.Name={0}", personCompany.Name); 
     Console.WriteLine("personCompany.PhNo={0}", personCompany.PhNo); 
     Console.WriteLine("personCompany.EmpNo={0}", personCompany.EmpNo); 
     Console.WriteLine("personCompany.Title={0}", personCompany.Title); 
5
mapper.MergeInto<PersonCar>(person, car) 

mit der akzeptierten Antwort als Erweiterungsmethoden, einfache und allgemeine Version:

public static TResult MergeInto<TResult>(this IMapper mapper, object item1, object item2) 
{ 
    return mapper.Map(item2, mapper.Map<TResult>(item1)); 
} 

public static TResult MergeInto<TResult>(this IMapper mapper, params object[] objects) 
{ 
    var res = mapper.Map<TResult>(objects.First()); 
    return objects.Skip(1).Aggregate(res, (r, obj) => mapper.Map(obj, r)); 
} 

Nach dem Konfigurieren der Zuordnung für jeden Eingabetyp:

IMapper mapper = new MapperConfiguration(cfg => 
{ 
    cfg.CreateMap<Person, PersonCar>(); 
    cfg.CreateMap<Car, PersonCar>(); 
}).CreateMapper(); 
+0

Wiederverwendbarkeit ist der Schlüssel! –

+0

Ich brauchte heute so etwas und die Einfachheit ist so elegant, thx! – PmanAce