Pewne produkty MS nauczyły mnie, że nie czyta się do nich dokumentacji bo (1) nie ma jej, (2) mówi nie prawdę (pomija bardzo ważne szczegóły). Przez to też często nie zwracam uwagi na dokumentację istniejącą na witrynach projektów Open Source. W tym wypadku nie zwróciłem uwagi, albo dokładniej, zwróciłem ale nie chciało mi się tego czytać – przejrzałem to co było, nie zobaczyłem tego co chciałem więc pomyślałem, że dupa i zapomniałem o stronie – na dokumentację od AutoMapper i opcję flattening która umożliwia mapowanie skomplikowanego obiektu do jego prostszej postaci.

Więc jeżeli wiesz co to AutoMapper, korzystałeś i wiesz jak wykorzystać flattening to sorki za taki błahy post :) jest on dla mnie ku pamięci bym po raz kolejny na idiotę nie wyszedł. Tak czy siak może zainteresuje Cię to iż AutoMapper wciąż jest rozwijany ale jego kod i kolejne wersje znajdują się na GitHub a nie na Codeplex :) o czym też dowiedziałem się… przypadkiem kiedy w końcu przewinąłem pierwszą stronę a nie jak głupi klikałem od razu download.

Dla przykładu mając następującą strukturę klas:

public class Complex
{
    public string Name { get; set; }
    public string Title { get; set; }
    public SubComplex Sub { get; set; }
    public IList<Item> Items { get; set; }
    public int GetTotal()
    {
        return Items.Count;
    }

    public string GetSmth
    {
        get { return Name + "test"; }
    }

    public Complex()
    {
        Items = new List<Item>();
        Sub = new SubComplex();
    }
}

public class SubComplex
{
    public string Subject { get; set; }
}

public class Item
{
    public int Val { get; set; }
}

Możemy ją zmapować na następującą klasę:

public class Flatten
{
    public string Title { get; set; }
    public string Name { get; set; }
    public string SubSubject { get; set; }
    public int Total { get; set; }
    public string Smth { get; set; }
}

Czyli, metoda GetTotal będzie z mapowana na własność Total (GetSmth na Smth)– jeżeli istnieje konwersja typów to się uda, jeżeli nie to zostanie zwrócony exception. Jeżeli byśmy posiadali własność Total i GetTotal (z get i set) w klasie docelowej, to mapowanie wykonałoby przypisanie wartości do tych dwóch własności. Jest to dość ważne, gdyż nagle możemy dostawać dziwne wartości lub niepoprawne mapowanie.

Oraz, Sub.Subject zostanie z mapowany na SubSubject. Uwaga jest taka sama jak poprzednio. Jakbyśmy mieli własność Sub która by była typem SubComplex to zarówno SubSubject jak i Sub byłoby z mapowane.

Szczerze w dokumentacji chyba właśnie tych pogrubień mi brakowało :)

Oczywiście jest to domyślna konfiguracja, i jak chcemy możemy to dopracować. Jednak warto wiedzieć o tym i nie pisać zbędnych linijek doprecyzowujących mapowanie bo potem może powstać kolejny Już Piątek :) na nieszczęścia wasze a szczęście swoje, skasowałem ten kod dość szybko ale możecie sobie już jego konstrukcję wyobrazić… :)

Pełny przykład:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using AutoMapper;

namespace AutoMapperFlattening
{
    class Program
    {
        static void Main(string[] args)
        {
            Complex complex = new Complex
                              {
                                  Name = "Some Name",
                                  Title = "Some Title",
                                  Items =
                                      {
                                          new Item { Val = 10 },
                                          new Item { Val = 10 },
                                          new Item { Val = 10 },
                                          new Item { Val = 10 },
                                          new Item { Val = 10 },
                                          new Item { Val = 10 },
                                      },
                                  Sub = new SubComplex { Subject = "Some Subject" }
                              };

            Mapper.CreateMap<Complex, Flatten>();

            Flatten flatten = Mapper.Map<Complex, Flatten>(complex);

            Debug.Assert(complex.Title == flatten.Title);
            Debug.Assert(complex.Name == flatten.Name);
            Debug.Assert(complex.Sub.Subject == flatten.SubSubject);
            Debug.Assert(complex.GetTotal() == flatten.Total);
            Debug.Assert(complex.GetSmth == flatten.Smth);

            Console.ReadLine();
        }
    }

    public class Complex
    {
        public string Name { get; set; }
        public string Title { get; set; }
        public SubComplex Sub { get; set; }
        public IList<Item> Items { get; set; }
        public int GetTotal()
        {
            return Items.Count;
        }

        public string GetSmth
        {
            get { return Name + "test"; }
        }

        public Complex()
        {
            Items = new List<Item>();
            Sub = new SubComplex();
        }
    }

    public class SubComplex
    {
        public string Subject { get; set; }
    }

    public class Item
    {
        public int Val { get; set; }
    }

    public class Flatten
    {
        public string Title { get; set; }
        public string Name { get; set; }
        public string SubSubject { get; set; }
        public int Total { get; set; }
        public string Smth { get; set; }
    }
}

1 KOMENTARZ

  1. O mapowaniu wyniku działania metod nie wiedziałem, spoko:).
    A co do codeplex/github… trochę mnie to już męczy. Jak znajduję fajny projekt to muszę przekopać się przez codeplex, github, bitbucket i sourceforge żeby mieć pewność, że faktycznie patrzę na najnowszą wersję kodu. Powinni usuwać nieaktualne witryny projektów, demet, a nie robić jakiś jeden mały pliczek "readme.txt" o zawartości "moved to…"

Comments are closed.