Artykuł

freeimages.com freeimages.com
sie 24 2014
0

Biblioteki warte poznania w C# - AutoMapper

Projektowanie aplikacji bywa ciężkie, szczególnie w początkowej fazie, kiedy to musimy podjąć wiele ważnych decyzji. Trzeba wybrać architekturę, język, wszelkiej maści frameworki itp. Musimy też pomyśleć o wzorcach architektonicznych. Ostatnio np. sporo pisałem o MVC, a jest przecież jeszcze bardzo popularny MVVM, czy MVP. Dlaczego o tym wszystkim piszę? Ano dlatego że przy używaniu tego rodzaju wzorców często pojawia się problem z modelowaniem aplikacji.

Wyobraźmy sobie np. aplikację opartą o wzorzec MVVM, w którym model domeny tworzą klasy POCO wykorzystywane przez Entity Framework. W takim przypadku musimy również utworzyć encje ViewModel. Siłą rzeczą pojawi się sporo przypadków, kiedy to klasy modelu danych oraz klasy ViewModel będą bardzo zbliżone. Czy w takim przypadku będziemy zmuszeni przepisywać wartości obiektów pole po polu? Nie. Można to na szczęście zrobić w bardziej elegancki sposób:-)

Charakterystyka i zastosowanie

AutoMapper to bardzo przydatna biblioteka, która jest w stanie przepisać wartości obiektu pewnego typu, do analogicznych właściwości w drugim obiekcie, który posiada inny typ. W przypadku gdy pola różnią się nazwami, istnieje możliwość stworzenia mapowania uwzględniającego różnice między oboma klasami. Biblioteka obsługuje również typy zagnieżdżone, dzięki czemu możliwe jest mapowanie nawet bardzo złożonych struktur.

Przepisywanie właściwości obiektów nie jest rzeczą trudną, aczkolwiek jest to proces mozolny i nudny. Łatwo jest tu również popełnić błąd tworząc ręczne mapowania. Narzędzia typu AutoMapper wykorzystujemy głównie w sytuacji, gdy tworzymy rozbudowane aplikacje, w których możemy rozróżnić warstwy danych oraz prezentacji. To właśnie tutaj biblioteka ta daje najwięcej możliwości, ponieważ za pomocą kilku linijek kodu, umożliwia przepisanie bardzo złożonych obiektów.

Z pozoru wydaje się, że w przypadku tego rodzaju narzędzia, nie potrzebujemy bogatego wachlarza funkcjonalności, dlatego też zawsze mocno zadziwia mnie fakt, ile przydatnych rzeczy umieścił autor w tej bibliotece. Poniżej skrócona lista najważniejszych funkcjonalności:

  • Automatyczne mapowanie obiektów o identycznych właściwościach
  • Mapowanie obiektów złożonych
  • Mapowanie właściwości o różnych nazwach
  • Automatyczne zastąpienie wartości null
  • Możliwość konwertowania wartości do innego typu
  • Szerokie wsparcie dla LINQ

Kiedy warto zastosować bibliotekę AutoMapper?

Z biblioteki AutoMapper warto skorzystać za każdym razem, gdy w naszej aplikacji musimy transferować dane ze zbliżonych obiektów, które różnią się jednak typem. Z taką sytuacją będziemy mieli najczęściej styczność w przypadku aplikacji wielowarstwowych, w których to encje modelu mogą różnić się od klas dostępnych w warstwie prezentacji. W takiej sytuacji AutoMapper będzie niezastąpiony, ponieważ nie tylko przepisze za nas wszystkie właściwości, ale zadba również o poprawność tych danych.

Przykład praktyczny

Wydaje mi się że wystarczy już teorii jak na jeden skromny post o bibliotece. Najwyższy więc czas zobaczyć jak sprawuje się ona w praktyce. AutoMapper jest dostępny za darmo i możemy go bez żadnych przeszkód pobrać z NuGeta używając managera pakietów w VS.

Do testów wykorzystamy dwie proste klasy: PersonModel oraz PersonViewModel. W pierwszym scenariuszu będą one miały dokładnie takie same właściwości, natomiast w drugim podejściu zmienimy nazwę jednego z pól, by zademonstrować funkcjonalność mapowania. Poniżej cały kod dla pierwszego wariantu:

using AutoMapper;
using System;
namespace AutoMapperTest
{
    class PersonModel
    {
        public int PersonId { get; set; }
        public string PersonFirstName { get; set; }
        public string PersonLastName { get; set; }
        public string PersonPhone { get; set; }
    }

    class PersonViewModel
    {
        public int PersonId { get; set; }
        public string PersonFirstName { get; set; }
        public string PersonLastName { get; set; }
        public string PersonPhone { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            PersonModel personModel = new PersonModel
            {
                PersonId = 1,
                PersonFirstName = "Jan",
                PersonLastName = "Kowalski",
                PersonPhone = "+48611234345"
            };

            Mapper.CreateMap<PersonModel, PersonViewModel>();
            PersonViewModel personViewModel = 
				Mapper.Map<PersonViewModel>(personModel);

            Console.WriteLine("Imię i nazwisko: {0} {1}", 
				personViewModel.PersonFirstName, 
				personViewModel.PersonLastName);
            Console.ReadKey();
        }
    }
}

Jak widać cały kod jest bardzo prosty. Kluczowe dla nas są linie 33-35. W pierwszej z nich tworzymy proste mapowanie w którym typem źródłowym jest PersonModel, a typem docelowym PersonViewModel. W liniach 34-35 wywołujemy już konkretną operację mapowania dwóch obiektów. Wydaje mi się, że składnia jest na tyle prosta, że nie wymaga ona jakiś dodatkowych wyjaśnień.

Przypadek drugi wymaga dwóch korekt. W linii 16 zmieniamy nazwę pola PersonFirstName na PersonName:

public string PersonName { get; set; }

Natomiast w linii 34 zaktualizujemy mapowanie, gdzie wprost określimy, że PersonFirstName z klasy PersonModel odpowiada polu PersonName w klasie PersonViewModel:

Mapper.CreateMap<PersonModel, PersonViewModel>()
	.ForMember(dest => dest.PersonName, opt =>
	opt.MapFrom(src => src.PersonFirstName));

Konstrukcja ta działa w trybie łańcuchowym, co oznacza że mając kilka różnych właściwości do zmapowania, możemy to zrobić w jednym wywołaniu.

Powyższy przykład to tylko wycinek funkcjonalności AutoMappera. Sama biblioteka oferuje znacznie więcej. Zachęcam do własnych eksperymentów;-)

Metryka

Podoba Ci się ten wpis? Powiedz o tym innym!

Send to Kindle

Komentarze

blog comments powered by Disqus