Zgodnie z tym, co napisałam w poprzednim poście, dzisiaj opisuję zastosowanie w projekcie AutoMappera.
Przykład zastosowania AutoMappera
Moje wcześniejsze rozwiązanie wyglądało następująco: miałam klasę GamerMapper, a w nim 2 metody:
- MapToGamerViewModel, która z obiektu Gamer tworzyła obiekt GamerViewModel
- MapToGamerList, która z listy obiektów Gamer tworzyła listę obiektów GamerViewModel (wykorzystywała wcześniejszą metodę)
public class GamerMapper { public static IEnumerable<GamerViewModel> MapToGamerList(IEnumerable<Gamer> gamerList) { return gamerList.Select(x => MapToGamerViewModel(x)).ToList(); } public static GamerViewModel MapToGamerViewModel(Gamer gamer) { if (gamer == null) { return null; } else { return new GamerViewModel() { Id = gamer.Id.ToString(), Nick = gamer.Nick, Name = gamer.Name, Surname = gamer.Surname, Email = gamer.Email, Age = gamer.Age, City = gamer.City, Street = gamer.Street }; } } }
Po zmianach klasa GamerMapper została przekształcona w klasę GamerProfile dziedziczącą po klasie AutoMapper.Profile. W jej kostruktorze jest zadeklarowane jedno mapowanie: z obiektu Gamer do obiektu GamerViewModel.
Wygląda to tak:
public class GamerProfile : Profile { public GamerProfile() { CreateMap<Gamer, GamerViewModel>(); } }
Wywołanie mappera jest bardzo proste, zarówno dla listy, jak i pojedynczego obiektu:
var gamerViewModel = Mapper.Map<GamerViewModel>(gamer); var gamerViewModelList = Mapper.Map&<List<GamerViewModel>>(gamerList);
Konfiguracja AutoMappera
Tyle zmian w kodzie. Oczywiście musiałam najpierw dodać AutoMappera do mojej aplikacji. Ściągnęłam paczkę z nugeta:
i dodałam konfigurację każdego profilu w pliku Global.asax.cs
builder.RegisterType<GamerProfile>().SingleInstance();
Błąd Mapper not initialized
Już myślałam, że zadziała, ale dostałam błąd:
“Mapper not initialized. Call Initialize with appropriate configuration.”
Okazało się, że zapomniałam zainicjalizować mój mapper. Wystarczyło w pliku Global.asax.cs zdefiniować i wywołać metodę Initialize():
public static void InitializeAutoMapper() { Mapper.Initialize(x => { x.AddProfile<GamerProfile>(); } ); }
Po użyciu tej metody okazało się, że rejestracja typów (przedstawiona w akapicie Konfiguracja) nie jest potrzebna.
Podsumowanie
Działa!
Został mi do rozwiązania jeszcze jeden problem: mapowanie na podstawie 2 źródeł do 1 obiektu. Nie udało mi się na razie znaleźć rozwiązania, więc następny wpis będzie zapewne o tym.
PS – Link do kolejnej części dotyczącej AutoMappera znajdziecie tutaj.
2 źródła do 1 obiektu można przemapować, używając niegenerycznej metody Map: Mapper.Map(from, to) i wywołując ją wielokrotnie z różnymi źródłami i tym samym celem. Przykład pierwszy z brzegu: https://stackoverflow.com/questions/21413273/automapper-convert-from-multiple-sources
PolubieniePolubione przez 1 osoba
Update: ta metoda jak najbardziej jest generyczna, to był tylko skrót myślowy, że nie trzeba podawać parametrów typu.
PolubieniePolubienie
Dziękuję za radę!
PolubieniePolubienie
Pingback: Refactoring: AutoMapper cz. 2 – programmer-girl
Pingback: Refactoring: AutoMapper cz. 3 – programmer-girl