Czy serializacja wyklucza stosowanie wstrzykiwania zależności?

9

Proste pytanie: Rozumiem, że serializacja w języku C # wymaga domyślnych konstruktorów. Wykluczałoby to możliwość użycia DI wstrzykniętego przez konstruktora (co jest moim zdaniem ulubionym stylem DI, w moim czytaniu [potrzebne źródło] ). Czy to naprawdę jest sytuacja albo, czy coś mi brakuje?

(Pytanie poboczne): Czy kontenery IoC w jakiś sposób ustępują temu kompromisowi?

kmote
źródło
This would eliminate the possibility of using Constructor injected DI-- Dlaczego? Nadal możesz sparametryzować instruktorów, pod warunkiem, że dołączasz domyślnego konstruktora do celów serializacji (domyślny konstruktor może być prywatny, jeśli chcesz).
Robert Harvey
@RobertHarvey: Czuję się trochę gęsty, ale nie do końca cię rozumiem. Co to jest „instruktor sparametryzowany”? (literówka?) Po zdserializowaniu obiektu nie mogę go ponownie zbudować. Sugerujesz, żebym użył zastrzyku właściwości / ustawiacza dla obiektu o domyślnej konstrukcji?
kmote
1
Konstruktor sparametryzowany to taki z parametrami. Zakładam tutaj, że deserializacja zachodzi z danych uzyskanych z obiektu, który został poprawnie skonstruowany przy użyciu wstrzykiwania zależności. Nie musisz budować obiektu podczas deserializacji; był już wcześniej zbudowany.
Robert Harvey
1
Nie, nie pomylisz się. Tak to działa. Pomyśl o tym jak o zastrzyku tylnych drzwi. Nie otrzymasz żadnej weryfikacji, ale zadziała. Zauważ, że BinaryFormatter i DataContractSerializer nie wymagają domyślnych konstruktorów.
Robert Harvey
1
Żeby było jasne, cała deserializacja nie polega na wypełnieniu stanu w obiekcie wartościami określonymi w obiekcie XML. Wykorzystuje Reflection, aby to osiągnąć, i omija każdą formę logiki sprawdzania poprawności konstruktora, więc z perspektywy DI jest oszustwem, chyba że te wartości XML pierwotnie pochodziły od obiektu zbudowanego przez zwykłą DI.
Robert Harvey

Odpowiedzi:

6

Nie jest możliwe odserializowanie obiektu, a także wstrzyknięcie zależności do innego, już istniejącego obiektu, w jednym kroku w języku C #, przy użyciu standardowych mechanizmów serializacji. Zamiast tego będziesz musiał użyć wstrzykiwania właściwości, najpierw konstruując obiekt za pomocą deserializatora, a następnie wstrzykiwając zależność. W przypadku większości rzeczywistych aplikacji nie uważam tego za prawdziwą wadę - jeśli masz możliwą do serializacji klasę modelu danych, która ma również zależności od innych klas modeli innych niż dane, powinieneś sprawdzić, czy klasa modelu danych może mieć już za dużo obowiązków.

Jeśli naprawdę Ci to przeszkadza, możesz rozważyć zawijanie obiektu możliwego do serializacji za pomocą klasy dekoratora, w której możesz przekazać program do serializacji i dodatkowe zależności przez konstruktor. To opakowanie wykonuje następnie dwa kroki (odserializowanie zawiniętego obiektu i wstrzyknięcie właściwości) w swoim konstruktorze.

Doktor Brown
źródło
1

Rozwiązuję ten problem w ten sposób: wstrzykiwanie fabryk zależności. W tych fabrykach najpierw rozwiązuje się zależność, ponieważ jest ona rejestrowana w kontenerze, a następnie „deserializuje” wszystkie pozostałe dane: json.net pozwala wypełnić pola w istniejącym obiekcie.

Ponieważ kod fabryk idzie w parze z kodem okablowania kontenera IoC, nie sądzę, że używanie container.Resolvewewnątrz fabryki narusza zasadę, którą containernależy stosować tylko w jednym miejscu w kodzie: gdzie odbywa się całe okablowanie.

Obecnie próbuję uczynić ten proces automatycznym (w przeciwieństwie do tego, w czym testowałem to podejście) za pomocą refleksji. Tak, niewiele pozostało z samej deserializacji json.net, jej część została zastąpiona niestandardowym kodem, ale myślę, dlaczego warto.

Jakie były twoje ostatnie przemyślenia / decyzje w tej sprawie? Po przeczytaniu tego postu widzę dwa sposoby: deserializować, a następnie wstrzyknąć; lub wstrzyknąć, a następnie deserializować (wypełnić). I wciąż uważam, że moja droga jest lepsza. Z przyjemnością usłyszę argumenty w przeciwieństwie do tego (myślę, że moja droga może być lepsza dla mojej sprawy, ale nie mogę żywo wyobrazić sobie dobrych alternatywnych przypadków, w których się nie powiedzie, tylko kilka drobnych domysłów)

jungle_mole
źródło