Предотвращает ли сериализация использование инъекций зависимостей?


9

Простой вопрос: я понимаю, что сериализация в C # требует конструкторов по умолчанию. Это исключило бы возможность использования встроенного DI конструктора (который обычно является предпочтительным стилем DI, в моем чтении [цитата нужна] ). Так это действительно или-или ситуация, или я что-то упустил?

(Дополнительный вопрос): Контейнеры IoC как-то обходят этот компромисс?


This would eliminate the possibility of using Constructor injected DI-- Почему? У вас все еще могут быть параметризованные инструкторы, если вы включаете конструктор по умолчанию для целей сериализации (конструктор по умолчанию может быть закрытым, если хотите).
Роберт Харви

@RobertHarvey: Я чувствую себя немного глупо, но я не совсем понимаю тебя. Что такое «параметризованный инструктор»? (опечатка?) После десериализации объекта я не могу создать его снова. Вы предлагаете использовать инъекцию свойства / сеттера для объекта по умолчанию?
kmote

1
Параметризованный конструктор - это один с параметрами. Я предполагаю, что десериализация происходит из данных, которые были получены из объекта, который был правильно построен с использованием внедрения зависимостей. Вам не нужно создавать объект во время десериализации; это было уже построено раньше.
Роберт Харви

1
Нет, вы не ошиблись. Вот как это работает. Думайте об этом как инъекция в заднюю дверь. Вы не получите никакой проверки, но это сработает. Обратите внимание, что BinaryFormatter и DataContractSerializer не требуют конструкторов по умолчанию.
Роберт Харви

1
Чтобы было ясно, вся десериализация выполняет заполнение состояния вашего объекта значениями, указанными в объекте XML. Он использует Reflection для достижения этой цели и обходит любую форму логики проверки конструктора, поэтому с точки зрения DI это обман, если только эти значения XML изначально не были получены от объекта, созданного с помощью обычного DI.
Роберт Харви

Ответы:


6

Невозможно десериализовать объект, а также внедрить зависимость от другого, уже существующего объекта, за один шаг в C #, используя стандартные механизмы сериализации. Вместо этого вам придется использовать внедрение свойства, сначала создавая объект с помощью десериализатора, а затем вводя зависимость. Для большинства реальных приложений я не считаю это реальным недостатком - если у вас есть сериализуемый класс модели данных, который также имеет зависимости от других классов, отличных от модели данных, вам следует проверить, может ли ваш класс модели данных иметь уже слишком много обязанностей.

Если это действительно беспокоит вас, вы можете обернуть ваш сериализуемый объект классом декоратора, где вы можете передать десериализатор и дополнительные зависимости через конструктор. Затем эта оболочка выполняет два шага (десериализация обернутого объекта и внедрение свойства) в своем конструкторе.


1

Я решаю эту проблему следующим образом: вводить фабрики зависимостей. На этих фабриках сначала разрешите зависимость, как она зарегистрирована в контейнере, а затем «десериализуйте» все оставшиеся данные: json.net позволяет заполнять поля в существующем объекте.

Поскольку код фабрики совпадает с кодом проводки контейнера IoC, я не думаю, что использование container.Resolveвнутри фабрики нарушает правило, которое containerдолжно использоваться только в одном месте кода: где происходит вся проводка.

На данный момент я пытаюсь сделать этот процесс автоматическим (в отличие от того, на котором я тестировал этот подход), используя рефлексию. Да, от самой десериализации json.net осталось немного, часть заменена пользовательским кодом, но я думаю, зачем это беспокоить.

Кроме того, каковы были ваши последние мысли / решения по этому вопросу? Прочитав этот пост, я вижу два пути: десериализовать, затем ввести; или ввести, затем десериализовать (заполнить). И я все еще считаю, что мой путь лучше. Будем рады услышать аргументы в противовес этому (я считаю, что мой путь может быть лучше для моего случая, но я не могу наглядно представить хорошие альтернативные случаи, когда он терпит неудачу, только некоторые незначительные предположения)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.