¿La serialización impide el uso de la inyección de dependencia?

9

Pregunta simple: entiendo que la serialización en C # requiere constructores predeterminados. Esto eliminaría la posibilidad de usar el DI inyectado por el constructor (que generalmente es el estilo preferido de DI, en mi lectura [cita requerida] ). Entonces, ¿es realmente una situación de uno u otro, o me estoy perdiendo algo?

(Pregunta secundaria): ¿Los contenedores de IoC evitan esta compensación de alguna manera?

kmote
fuente
This would eliminate the possibility of using Constructor injected DI-- ¿Por qué? Todavía puede tener instructores parametrizados, siempre que incluya un constructor predeterminado para fines de serialización (el constructor predeterminado puede ser privado, si lo desea).
Robert Harvey
@RobertHarvey: Me siento un poco denso, pero no te entiendo. ¿Qué es un "instructor parametrizado"? (¿error tipográfico?) Una vez que un objeto se ha deserializado, no puedo volver a construirlo. ¿Sugiere que use la inyección de propiedad / configuración en un objeto predeterminado?
kmote
1
Un constructor parametrizado es uno con parámetros. Asumo aquí que la deserialización se produce a partir de datos que se derivaron de un objeto que se construyó correctamente mediante inyección de dependencia. No tiene que construir el objeto durante la deserialización; ya fue construido antes.
Robert Harvey
1
No, no te equivocas. Asi es como funciona. Piense en ello como una inyección en la puerta de atrás. No obtendrá ninguna validación, pero funcionará. Tenga en cuenta que BinaryFormatter y DataContractSerializer no requieren constructores predeterminados.
Robert Harvey
1
Para que quede claro, lo único que hace la deserialización es llenar el estado de su objeto con los valores que se especifican en el objeto XML. Utiliza Reflection para lograr esto, y omite cualquier forma de lógica de validación del constructor, por lo que desde la perspectiva de DI, es trampa, a menos que esos valores XML provengan originalmente de un objeto construido a través de DI ordinaria.
Robert Harvey

Respuestas:

6

No es posible deserializar un objeto y también inyectar una dependencia a otro objeto ya existente, en un paso en C #, utilizando los mecanismos de serialización estándar. En su lugar, deberá usar la inyección de propiedades, primero construyendo el objeto usando el deserializador, luego inyectando la dependencia. Para la mayoría de las aplicaciones del mundo real, no considero que esto sea un verdadero inconveniente: si tiene una clase de modelo de datos serializable, que también depende de otras clases de modelos que no son de datos, debe verificar si su clase de modelo de datos puede tener Demasiadas responsabilidades ya.

Si eso realmente le molesta, puede considerar envolver su objeto serializable con una clase de decorador, donde puede pasar el deserializador y las dependencias adicionales a través del constructor. Ese contenedor luego ejecuta los dos pasos (deserialización del objeto envuelto e inyección de propiedad) en su constructor.

Doc Brown
fuente
1

Estoy resolviendo este problema así: inyectando fábricas de dependencias. En esas fábricas, primero resuelva la dependencia tal como está registrada en el contenedor, luego "deserialice" todos los datos restantes: json.net permite llenar campos en objetos existentes.

Como el código de las fábricas va junto con el código de cableado del contenedor de IoC, no creo que el uso container.Resolvedentro de la fábrica viole la regla, que containerdebe usarse solo en un lugar en el código: donde ocurre todo el cableado.

A partir de ahora, estoy tratando de hacer que este proceso sea automático (a diferencia de lo que he estado probando con ese enfoque) usando la reflexión. Sí, no queda mucho de lo que queda de la deserialización de json.net, parte de ella se sustituye con un código personalizado, pero creo que por qué molestarse.

Además, ¿cuál fue su opinión / decisión final sobre el asunto? Después de leer esta publicación, veo dos formas: deserializar, luego inyectar; o inyectar, luego deserializar (poblar). Y todavía encuentro que mi camino es mejor. Estaré encantado de escuchar argumentos en oposición a esto (estoy considerando que mi camino puede ser mejor para mi caso, pero no puedo imaginar vívidamente buenos casos alternativos, donde falla, solo algunas conjeturas menores)

selva_mole
fuente