Chcę zadać kilka pytań na temat najlepszych praktyk dotyczących typów mapowania i korzystania z metod rozszerzenia w języku C #. Wiem, że ten temat był omawiany wiele razy w ciągu ostatnich kilku lat, ale przeczytałem wiele postów i nadal mam wątpliwości.
Problemem, który napotkałem, było rozszerzenie posiadanej przeze mnie klasy o funkcję „konwersji”. Powiedzmy, że mam klasę „Osoba” reprezentującą obiekt, który będzie używany przez jakąś logikę. Mam również klasę „Klient”, która reprezentuje odpowiedź zewnętrznego interfejsu API (w rzeczywistości będzie więcej niż jeden interfejs API, więc muszę mapować odpowiedź każdego interfejsu API na typ typowy: Osoba). Mam dostęp do kodu źródłowego obu klas i teoretycznie mogę tam implementować własne metody. Muszę przekonwertować klienta na osobę, aby zapisać go w bazie danych. Projekt nie korzysta z żadnych automatycznych mapowań.
Mam na myśli 4 możliwe rozwiązania:
Metoda .ToPerson () w klasie Consumer. To proste, ale wydaje mi się, że przełamujesz wzorzec pojedynczej odpowiedzialności, zwłaszcza że klasa Consumer jest również odwzorowana na inne klasy (niektóre wymagane przez inny zewnętrzny interfejs API), więc musiałaby zawierać wiele metod mapowania.
Konstruktor odwzorowań w klasie Person traktuje Konsumenta jako argument. Również łatwe i wydaje się, że łamanie wzorca pojedynczej odpowiedzialności. Musiałbym mieć wiele konstruktorów odwzorowywania (ponieważ będzie klasa z innego interfejsu API, zapewniająca te same dane co konsument, ale w nieco innym formacie)
Klasa konwerterów z metodami rozszerzeń. W ten sposób mogę napisać metodę .ToPerson () dla klasy Consumer, a kiedy inny API zostanie wprowadzony z własną klasą NewConsumer, mogę po prostu napisać inną metodę rozszerzenia i zachować wszystko w tym samym pliku. Słyszałem opinię, że metody rozszerzenia są ogólnie złe i powinny być stosowane tylko wtedy, gdy jest to absolutnie konieczne, więc to mnie powstrzymuje. W przeciwnym razie podoba mi się to rozwiązanie
Klasa konwertera / mapowania. Tworzę osobną klasę, która będzie obsługiwać konwersje i implementuję metody, które przyjmą instancję klasy źródłowej jako argument i zwrócą instancję klasy docelowej.
Podsumowując, mój problem można sprowadzić do liczby pytań (wszystko w kontekście do tego, co opisałem powyżej):
Czy umieszczenie metody konwersji w obiekcie (POCO?) (Jak metoda .ToPerson () w klasie Consumer) jest rozważane jako przełamanie wzorca pojedynczej odpowiedzialności?
Czy używanie konstruktorów konwertujących w klasie (podobnej do DTO) jest uważane za przełamanie wzorca pojedynczej odpowiedzialności? Zwłaszcza jeśli taką klasę można przekonwertować z wielu typów źródeł, więc byłoby wymaganych wiele konstruktorów konwertujących?
Czy stosowanie metod rozszerzenia przy jednoczesnym dostępie do oryginalnego kodu źródłowego klasy jest uważane za złą praktykę? Czy takie zachowanie może być wykorzystane jako realny wzór do rozdzielenia logiki, czy też jest to anty-wzór?
Personklasa jest DTO? czy zawiera jakieś zachowanie?