niedziela, 23 września 2012

Mapowanie obiektów - Extension Methods

Extension Methods można wykorzystać nie tylko do dodawania metod do istniejących klas, ale także jako najprostszy mechanizm mapujący. Nie musimy tworzyć całej biblioteki do mapowania, wystarczy dodać do klasy odpowiednią metodę np. Map.

Jako kod bazowy użyjemy obiekt encji tabeli:

Code:
    public class PersonEntity
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
    }

klasa którą chcemy uzyskać ma następującą strukturę:

Code:
    public class PersonView
    {
        public string FullName { get; set; }
        public string Address { get; set; }
    }

Kod mapowania:

Code:
    public static class Mappers
    {
             public static PersonView Map(this PersonEntity personEntity)
             {
                 return new PersonView
                            {
                                FullName = personEntity.FirstName + " " + personEntity.LastName,
                                Address = personEntity.Address
                            };
             }
    }

użycie sprowadza się do wywołania metody Map na obiekcie bazowym:

Code:
            var personEntity = new PersonEntity
                                   {
                                       Id = 1, Address = "Andrychowska 34, 10-124 Andrychów", Age = 31, FirstName = "Jan", LastName = "Kowalski"
                                   };
            var pv = personEntity.Map();

3 komentarze:

  1. "Nie musimy tworzyć całej biblioteki do mapowania" - mam nadzieję że nawet gdybyśmy całej biblioteki potrzebowali, to byśmy jej sami nie tworzyli ;) Po to są projekty jak np. ValueInjecter czy AutoMapper.

    Osobiście nie jestem pewien, czy wykorzystanie metody statycznej ma tutaj sens. Czemu nie zaimplementować np. metody FromEntity w samej klasie PersonView? Albo w ogóle osobnej klasy (wzorzec adapter)?

    Metody statyczne mają to do siebie, że "wiszą" w osobnych, statycznych klasach i nie jest automatycznie oczywiste, gdzie ich w razie czego szukać.

    Jeżeli nie ma jakichś konkretnych przeciwskazań, to w moim odczuciu warto dążyć do tego, by obiekt miał logikę dotyczącą samego siebie "pzzy sobie".

    Co więcej, ze statycznych klas nie da się dziedziczyć i nie można ich mockować, co może okazać się przeszkodą np. przy pisaniu testów.

    OdpowiedzUsuń
    Odpowiedzi
    1. Często jest tak, że korzystamy z innej biblioteki do której kodu nie mamy dostępu.

      Inny powód to zasada "Single Responsibility Principle".

      Usuń
  2. a nie lepiej tak ?

    PropertyInfo[] propslite = adifrowlite.GetType().GetProperties();

    foreach (PropertyInfo prp in propslite)
    {
    if (prp.Name == "qsl_all_rcvd")
    {
    string tmp = adifrow.qsl_rcvd + "/" + adifrow.lotw_qsl_rcvd + "/" + adifrow.eqsl_qsl_rcvd;
    adifrowlite.qsl_all_rcvd = tmp.Replace(" ", "");
    }

    else if (prp.Name.Contains(adifrow.GetType().GetProperty(prp.Name).Name))
    {
    PropertyInfo pi = typeof(ADIFRowLite).GetProperty(prp.Name);
    pi.SetValue(adifrowlite, (string)Extensions.GetPropValue(adifrow, prp.Name), null);
    }
    }

    OdpowiedzUsuń