Una aplicación con la que he estado trabajando falla cuando intento serializar tipos.
Una declaración como
XmlSerializer lizer = new XmlSerializer(typeof(MyType));
produce:
System.IO.FileNotFoundException occurred
Message="Could not load file or assembly '[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
Source="mscorlib"
FileName="[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
FusionLog=""
StackTrace:
at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
No defino ningún serializador especial para mi clase.
¿Como puedo solucionar este problema?
c#
xml-serialization
Irwin
fuente
fuente
Generate serialization assembly
menú desplegable a "Activado", en lugar de "Automático".Respuestas:
Lo creas o no, este es un comportamiento normal. Se produce una excepción, pero XmlSerializer la maneja, por lo que si la ignora, todo debería continuar bien.
Esto me pareció muy molesto, y ha habido muchas quejas sobre esto si buscas un poco, pero por lo que he leído, Microsoft no planea hacer nada al respecto.
Puede evitar las ventanas emergentes de excepción todo el tiempo mientras se depura si desactiva las excepciones de primera oportunidad para esa excepción específica. En Visual Studio, vaya a Depurar -> Excepciones (o presione Ctrl+ Alt+ E), Excepciones de Common Language Runtime -> System.IO -> System.IO.FileNotFoundException .
Puede encontrar información sobre otra forma de evitarlo en la publicación del blog C # XmlSerializer FileNotFound excepción (que analiza la herramienta XmlSerializerPreCompiler de Chris Sells ).
fuente
Como dijo Martin Sherburn, este es un comportamiento normal. El constructor del XmlSerializer primero intenta encontrar un ensamblado llamado [YourAssembly] .XmlSerializers.dll que debe contener la clase generada para la serialización de su tipo. Dado que dicha DLL aún no se ha generado (no lo están de forma predeterminada), se genera una excepción FileNotFoundException. Cuando eso sucede, el constructor de XmlSerializer detecta esa excepción, y el constructor de XmlSerializer genera la DLL automáticamente en tiempo de ejecución (esto se hace generando archivos fuente C # en el directorio% temp% de su computadora, luego compilándolos usando el compilador C #). Las construcciones adicionales de un XmlSerializer para el mismo tipo solo usarán el DLL ya generado.
La excepción es manejada por el constructor de XmlSerializer. No hay necesidad de hacer nada usted mismo, simplemente haga clic en 'Continuar' (F5) para continuar ejecutando su programa y todo estará bien. Si le molestan las excepciones que detienen la ejecución de su programa y aparecen un asistente de excepción, tiene 'Just My Code' desactivado o tiene la FileNotFoundException configurada para interrumpir la ejecución cuando se lanza, en lugar de cuando 'User- no manejado ".
Para habilitar 'Solo mi código', vaya a Herramientas >> Opciones >> Depuración >> General >> Habilitar solo mi código. Para desactivar la interrupción de la ejecución cuando se lanza FileNotFound, vaya a Depurar >> Excepciones >> Buscar >> ingrese 'FileNotFoundException' >> desactive la casilla de verificación 'Lanzar' de System.IO.FileNotFoundException.
fuente
FileNotFoundException
lanzará un . La diferencia no está en cómo se verifica la existencia del ensamblaje, sino en cómo generarlo una vez que se determina que falta. Antes, usaba la generación de código textual de C # con una llamada al compilador de C # para crear el IL. Comenzando con .NET 4.5, emite IL directamente, sin el uso de un compilador.File.Exists()
puede no ser suficiente. La ubicación de un ensamblaje no es un asunto simple, el tiempo de ejecución se ve en varias ubicaciones y creo que el comportamiento cambia de acuerdo con el entorno (aplicación de consola frente a ser alojado en IIS, etc.). Supongo que lo que debería haberse implementado fue unTryLoadAssembly()
o algo similar.En las propiedades del proyecto de Visual Studio (página "Build", si no recuerdo mal) hay una opción que dice "generar ensamblado de serialización". Intente encenderlo para un proyecto que genere [Contiene ensamblaje de MyType] .
fuente
Hay una solución para eso. Si utiliza
Debería evitar esa excepción. Esto funcionó para mí.
ADVERTENCIA: no lo use varias veces, o tendrá una pérdida de memoria
¡Perderá la memoria como loco si usa este método para crear instancias del
XmlSerializer
mismo tipo más de una vez!Esto se debe a que este método omite el almacenamiento en caché incorporado siempre que los constructores
XmlSerializer(type)
yXmlSerializer(type, defaultNameSpace)
(todos los demás constructores también omitan el almacenamiento en caché).Si utiliza algún método para crear un XmlSerializer que no sea a través de estos dos constructores, debe implementar su propio almacenamiento en caché o tendrá memoria de hemorragia.
fuente
XmlSerializer
mismo tipo más de una vez! Esto se debe a que este método omite el almacenamiento en caché incorporado siempre que los constructoresXmlSerializer(type)
yXmlSerializer(type, defaultNameSpace)
(todos los demás constructores también omitan el almacenamiento en caché). Si usa algún método para crear unoXmlSerializer
que no sea a través de estos dos constructores, debe implementar su propio almacenamiento en caché o tendrá una memoria de hemorragia.FromTypes
parece llenar el caché. Por lo tanto, debería ser una forma válida de calentar unXmlSerializer
caché vacío en una declaración (como sugiere el artículo), pero una forma realmente mala de recuperar algo de él (solo debe hacerse a través de los constructores más simples). En cualquier caso, no sabía que era un error, siempre pensé que se suponía que cualquier fuga (como losXmlSerializer
constructores más avanzados ). Ni siquiera habría considerado usarlo,FromTypes()
ya que puedes hacerlotypes.Select(t => new XmlSerializer(t))
.FromTypes
no es de prueba tiene su atractivo: incluso si se detectan todas las excepciones, es una operación costosa; El enfoque de "almacenar en caché a su manera" parece ser la única solución, ya que la única solución oficialmente admitida parece estar en un oscuro ensamblaje basado en la web. (editar: francamente, estoy a favor de transferir todo a los contratos de datos :))Me encontré con este problema exacto y no pude evitarlo con ninguna de las soluciones mencionadas.
Entonces finalmente encontré una solución. Parece que el serializador necesita no solo el tipo, sino también los tipos anidados. Cambiando esto:
A esto:
Solucionó el problema para mí. No más excepciones ni nada.
fuente
var xmlSerializer = new XmlSerializer(typeof(T), typeof(T).GetNestedTypes());
Mi solución es ir directamente a la reflexión para crear el serializador. Esto evita la carga extraña de archivos que causa la excepción. Empaqué esto en una función auxiliar que también se encarga de almacenar en caché el serializador.
fuente
Para evitar la excepción, debe hacer dos cosas:
Agregue el atributo System.Xml.Serialization.XmlSerializerAssembly a su clase. Reemplace 'MyAssembly' con el nombre del ensamblaje donde está MyClass.
Genere el archivo de serialización utilizando la utilidad sgen.exe e impleméntelo con el ensamblado de la clase.
'sgen.exe MyAssembly.dll' generará el archivo MyAssembly.XmlSerializers.dll
Estos dos cambios harán que .net encuentre directamente el ensamblado. Lo revisé y funciona en .NET Framework 3.5 con Visual Studio 2008
fuente
Esta excepción también puede ser atrapada por un asistente de depuración administrado (MDA) llamado BindingFailure.
Este MDA es útil si su aplicación está diseñada para enviarse con ensambles de serialización precompilados. Hacemos esto para aumentar el rendimiento de nuestra aplicación. Nos permite asegurarnos de que los ensambles de serialización preconstruidos estén siendo construidos adecuadamente por nuestro proceso de construcción y cargados por la aplicación sin ser reconstruidos sobre la marcha.
Realmente no es útil, excepto en este escenario, porque como han dicho otros carteles, cuando el constructor del serializador atrapa un error vinculante, el ensamblado de serialización se reconstruye en tiempo de ejecución. Por lo tanto, generalmente puede apagarlo.
fuente
La función XmlSerializer.FromTypes no produce la excepción, pero pierde la memoria. Es por eso que necesita almacenar en caché dicho serializador para cada tipo para evitar pérdidas de memoria para cada instancia creada.
Cree su propia fábrica de XmlSerializer y úsela simplemente:
La fábrica parece gustos:
Versión más complicada sin posibilidad de pérdida de memoria (alguien revise el código):
fuente
La resolución de errores de compilación, por otro lado, es muy complicada. Estos problemas se manifiestan en una FileNotFoundException con el mensaje:
Quizás se pregunte qué tiene que ver una excepción de archivo no encontrado con la creación de instancias de un objeto serializador, pero recuerde: el constructor escribe archivos C # e intenta compilarlos. La pila de llamadas de esta excepción proporciona buena información para respaldar esa sospecha. La excepción ocurrió mientras XmlSerializer intentaba cargar un ensamblado generado por CodeDOM llamando al método System.Reflection.Assembly.Load. La excepción no proporciona una explicación de por qué el ensamblado que se suponía que XmlSerializer debía crear no estaba presente. En general, el ensamblado no está presente porque la compilación falló, lo que puede suceder porque, en circunstancias excepcionales, los atributos de serialización producen código que el compilador de C # no puede compilar.
Nota: Este error también se produce cuando XmlSerializer se ejecuta en una cuenta o en un entorno de seguridad que no puede acceder al directorio temporal.
Fuente : http://msdn.microsoft.com/en-us/library/aa302290.aspx
fuente
En las propiedades del proyecto de Visual Studio hay una opción que dice "generar ensamblaje de serialización". Intente encenderlo para un proyecto que genere [Contiene ensamblaje de MyType].
fuente
Una clase personalizada para serializar:
He adjuntado el fragmento de código. Tal vez esto pueda ayudarte.
fuente
Estaba teniendo un problema similar e ignorar la excepción no funcionó para mí. Mi código estaba llamando a la configuración de NServiceBus
Configure.With(...).XmlSerializer()...
Lo que me solucionó fue cambiar la plataforma de mi proyecto.
fuente
Solo como referencia. Tomando de la respuesta y los comentarios de DB, vine con esta solución que está cerca de la solución de DB. Funciona bien en todos mis casos y es seguro para subprocesos. No creo que usar un ConcurrentDictionary hubiera estado bien.
Uso:
fuente
Su tipo puede hacer referencia a otros ensamblados que no se pueden encontrar ni en el GAC ni en su carpeta bin local ==> ...
¿Puede dar un ejemplo del tipo que desea serializar?
Nota: Asegúrese de que su tipo implemente Serializable.
fuente
Estaba recibiendo el mismo error, y fue debido al tipo que estaba tratando de deserializar al no tener un constructor sin parámetros predeterminado . Agregué un constructor y comenzó a funcionar.
fuente
¡Tuve el mismo problema hasta que utilicé una herramienta de terceros para generar la Clase desde el XSD y funcionó! Descubrí que la herramienta estaba agregando un código extra en la parte superior de mi clase. Cuando agregué este mismo código a la parte superior de mi clase original, funcionó. Esto es lo que agregué ...
fuente
ConcurrentDictionary
He visto muchas recomendaciones para usar un , pero no hay ejemplos sólidos de él, así que voy a lanzar mi sombrero en esta carrera de solución. No soy un desarrollador seguro para subprocesos, así que si este código no es sólido, hable por el bien de los que siguen.He visto otras publicaciones que involucran
ConcurrentDictionary
yLazy
cargan el valor. No estoy seguro de si eso es relevante aquí o no, pero aquí está el código para eso:fuente