sharp serialize serializar example deserializar c# xml-serialization

c# - serializar - XmlSerializer dando FileNotFoundException en el constructor



system xml serialization example c# (17)

Como dijo Martin Sherburn, este es un comportamiento normal. El constructor del XmlSerializer primero intenta encontrar un ensamblaje llamado [YourAssembly] .XmlSerializers.dll que debe contener la clase generada para la serialización de su tipo. Dado que tal DLL aún no se ha generado (no son de forma predeterminada), se emite una excepción FileNotFoundException. Cuando eso sucede, el constructor de XmlSerializer captura esa excepción y el constructor de XmlSerializer genera la DLL automáticamente en tiempo de ejecución (esto se hace generando archivos de origen C # en el directorio% temp% de su computadora, luego compilándolos usando el compilador de C #). Las construcciones adicionales de un XmlSerializer para el mismo tipo solo usarán la DLL ya generada.

ACTUALIZACIÓN: A partir de .NET 4.5, XmlSerializer ya no realiza la generación de código ni realiza la compilación con el compilador de C # para crear un ensamblaje de serializador en tiempo de ejecución, a menos que se lo obligue explícitamente a configurar un archivo de configuración ( useLegacySerializerGeneration ) Este cambio elimina la dependencia de csc.exe y mejora el rendimiento de inicio. Fuente: .NET Framework 4.5 Readme , sección 1.3.8.1.

La excepción es manejada por el constructor de XmlSerializer. No hay necesidad de hacer nada por sí 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 abre un ayudante de excepción, o bien ''Just My Code'' está desactivado, o bien tiene establecida la excepción FileNotFoundException para interrumpir la ejecución cuando se lanza, en lugar de cuando ''User- sin manejar ''.

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'' >> desmarque la casilla ''Lanzar'' de System.IO.FileNotFoundException.

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?


En las propiedades del proyecto de Visual Studio (página "Crear", si recuerdo bien) hay una opción que dice "generar ensamblaje de serialización". Intente activarlo para un proyecto que genere [Containing Assembly of MyType] .


En las propiedades del proyecto de Visual Studio hay una opción que dice "generar ensamblaje de serialización". Intente activarlo para un proyecto que genere [Containing Assembly of MyType].


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 ensamblajes de serialización precompilados. Hacemos esto para aumentar el rendimiento de nuestra aplicación. Nos permite asegurarnos de que los ensamblajes de serialización predefinidos se estén construyendo correctamente mediante nuestro proceso de compilación, y que la aplicación los cargue sin volver a construirlos al vuelo.

Realmente no es útil, excepto en este escenario, porque, como han dicho otros carteles, cuando el constructor Serializer atrapa un error de enlace, el ensamblaje de serialización se reconstruye en el tiempo de ejecución. Así que usualmente puedes apagarlo.


Estaba teniendo un problema similar, y ignorar la excepción no me funcionó. Mi código estaba llamando a la configuración de NServiceBus Configure.With(...).XmlSerializer()...

Lo que me lo arregló fue cambiar la plataforma de mi proyecto.

  1. Vaya a Build / Configuration Manager ...
  2. Encuentra tu proyecto y cambia la plataforma (en mi caso de x86 a cualquier CPU)

Hay una solución para eso. Si utiliza

XmlSerializer lizer = XmlSerializer.FromTypes(new[] { typeof(MyType) })[0];

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 de XmlSerializer para el mismo tipo más de una vez!

Esto se debe a que este método omite el almacenamiento en caché incorporado siempre que los XmlSerializer(type) y XmlSerializer(type, defaultNameSpace) (todos los demás constructores también omitan el caché).

Si usas cualquier método para crear un XmlSerializer que no sea a través de estos dos constructores, debes implementar tu propio almacenamiento en caché o sufrirás una hemorragia en la memoria.


La función XmlSerializer.FromTypes no lanza la excepción, pero pierde la memoria. Es por eso que necesita almacenar en memoria caché ese serializador para cada tipo para evitar pérdidas de memoria en cada instancia creada.

Cree su propia fábrica de XmlSerializer y utilícela simplemente:

XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(MyType));

La fábrica se parece a:

public static class XmlSerializerFactoryNoThrow { public static Dictionary<Type, XmlSerializer> _cache = new Dictionary<Type, XmlSerializer>(); private static object SyncRootCache = new object(); /// <summary> /// //the constructor XmlSerializer.FromTypes does not throw exception, but it is said that it causes memory leaks /// http://.com/questions/1127431/xmlserializer-giving-filenotfoundexception-at-constructor /// That is why I use dictionary to cache the serializers my self. /// </summary> public static XmlSerializer Create(Type type) { XmlSerializer serializer; lock (SyncRootCache) { if (_cache.TryGetValue(type, out serializer)) return serializer; } lock (type) //multiple variable of type of one type is same instance { //constructor XmlSerializer.FromTypes does not throw the first chance exception serializer = XmlSerializer.FromTypes(new[] { type })[0]; //serializer = XmlSerializerFactoryNoThrow.Create(type); } lock (SyncRootCache) { _cache[type] = serializer; } return serializer; } }

Versión más complicada sin posibilidad de pérdida de memoria (por favor, alguien revise el código):

public static XmlSerializer Create(Type type) { XmlSerializer serializer; lock (SyncRootCache) { if (_cache.TryGetValue(type, out serializer)) return serializer; } lock (type) //multiple variable of type of one type is same instance { lock (SyncRootCache) { if (_cache.TryGetValue(type, out serializer)) return serializer; } serializer = XmlSerializer.FromTypes(new[] { type })[0]; lock (SyncRootCache) { _cache[type] = serializer; } } return serializer; } }


Lo creas o no, este es un comportamiento normal. XmlSerializer lanza una excepción, pero la maneja, por lo tanto, si simplemente la ignora, todo debería continuar bien.

He encontrado esto 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 obtener ventanas emergentes de excepción todo el tiempo mientras realiza la depuración 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 manera de evitarlo en la publicación del blog C # XmlSerializer FileNotFound excepción (la herramienta XmlSerializerPreCompiler de Chris Sells).


Me encontré con este problema exacto y no pude evitarlo por ninguna de las soluciones mencionadas.

Entonces finalmente encontré una solución. Parece que el serializador no solo necesita el tipo, sino también los tipos anidados. Cambiando esto:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

A esto:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T).GetNestedTypes());

Arreglado el problema para mí. No más excepciones ni nada.


Mi solución es ir directamente a la reflexión para crear el serializador. Esto evita la carga de archivos extraños que causa la excepción. Empaqueté esto en una función auxiliar que también se encarga de almacenar en caché el serializador.

private static readonly Dictionary<Type,XmlSerializer> _xmlSerializerCache = new Dictionary<Type, XmlSerializer>(); public static XmlSerializer CreateDefaultXmlSerializer(Type type) { XmlSerializer serializer; if (_xmlSerializerCache.TryGetValue(type, out serializer)) { return serializer; } else { var importer = new XmlReflectionImporter(); var mapping = importer.ImportTypeMapping(type, null, null); serializer = new XmlSerializer(mapping); return _xmlSerializerCache[type] = serializer; } }


Para evitar la excepción necesitas hacer dos cosas:

  1. Agregue un atributo a la clase serializada (espero que tenga acceso)
  2. Generar el archivo de serialización con sgen.exe

Agregue el atributo System.Xml.Serialization.XmlSerializerAssembly a su clase. Reemplace ''MyAssembly'' con el nombre del ensamblaje donde se encuentra MyClass.

[Serializable] [XmlSerializerAssembly("MyAssembly.XmlSerializers")] public class MyClass { … }

Genere el archivo de serialización utilizando la utilidad sgen.exe y desplácelo con el ensamblaje de la clase.

''sgen.exe MyAssembly.dll'' generará el archivo MyAssembly.XmlSerializers.dll

Estos dos cambios harán que .net encuentre directamente el ensamblaje. Lo comprobé y funciona en .NET framework 3.5 con Visual Studio 2008


Recibí el mismo error y se debió a que estaba intentando deserializar el tipo de no tener un constructor predeterminado sin parámetros . Añadí un constructor, y empezó a funcionar.


Sólo 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.

using System; using System.Collections.Generic; using System.Xml.Serialization; namespace HQ.Util.General { public class XmlSerializerHelper { private static readonly Dictionary<Type, XmlSerializer> _dictTypeToSerializer = new Dictionary<Type, XmlSerializer>(); public static XmlSerializer GetSerializer(Type type) { lock (_dictTypeToSerializer) { XmlSerializer serializer; if (! _dictTypeToSerializer.TryGetValue(type, out serializer)) { var importer = new XmlReflectionImporter(); var mapping = importer.ImportTypeMapping(type, null, null); serializer = new XmlSerializer(mapping); return _dictTypeToSerializer[type] = serializer; } return serializer; } } } }

Uso:

if (File.Exists(Path)) { using (XmlTextReader reader = new XmlTextReader(Path)) { // XmlSerializer x = new XmlSerializer(typeof(T)); var x = XmlSerializerHelper.GetSerializer(typeof(T)); try { options = (OptionsBase<T>)x.Deserialize(reader); } catch (Exception ex) { Log.Instance.AddEntry(LogType.LogException, "Unable to open Options file: " + Path, ex); } } }


Solución de problemas de errores de compilación por otro lado es muy complicado. Estos problemas se manifiestan en una excepción FileNotFoundException con el mensaje:

File or assembly name abcdef.dll, or one of its dependencies, was not found. File name: "abcdef.dll" at System.Reflection.Assembly.nLoad( ... ) at System.Reflection.Assembly.InternalLoad( ... ) at System.Reflection.Assembly.Load(...) at System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly()

Puede preguntarse qué tiene que ver la excepción de un 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 apoyar esa sospecha. La excepción se produjo mientras el XmlSerializer intentaba cargar un conjunto generado por CodeDOM llamando al método System.Reflection.Assembly.Load. La excepción no proporciona una explicación de por qué el ensamblaje que se suponía que XmlSerializer debía crear no estaba presente. En general, el ensamblaje no está presente porque la compilación falló, lo que puede suceder porque, en circunstancias excepcionales, los atributos de serialización producen un código que el compilador de C # no compila.

Nota Este error también se produce cuando XmlSerializer se ejecuta con una cuenta o un entorno de seguridad que no puede acceder al directorio temporal.

Fuente : http://msdn.microsoft.com/en-us/library/aa302290.aspx


Su tipo puede hacer referencia a otros conjuntos que no se pueden encontrar ni en el GAC ni en su carpeta de contenedores local ==> ...

"o una de sus dependencias. El sistema no puede encontrar el archivo especificado"

¿Puedes dar un ejemplo del tipo que quieres serializar?

Nota: asegúrese de que su tipo implementa Serializable.


Tuve el mismo problema hasta que usé una herramienta de terceros para generar la clase desde el XSD y ¡funcionó! Descubrí que la herramienta estaba agregando un código adicional 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é ...

#pragma warning disable namespace MyNamespace { using System; using System.Diagnostics; using System.Xml.Serialization; using System.Collections; using System.Xml.Schema; using System.ComponentModel; using System.Xml; using System.Collections.Generic; [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1064.2")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)] public partial class MyClassName { ...


Una clase personalizada para serializar:

[Serializable] public class TestClass { int x = 2; int y = 4; public TestClass(){} public TestClass(int x, int y) { this.x = x; this.y = y; } public int TestFunction() { return x + y; } }

He adjuntado el fragmento de código. Tal vez esto pueda ayudarte.

static void Main(string[] args) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(TestClass)); MemoryStream memoryStream = new MemoryStream(); XmlTextWriter xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); TestClass domain = new TestClass(10, 3); xmlSerializer.Serialize(xmlWriter, domain); memoryStream = (MemoryStream)xmlWriter.BaseStream; string xmlSerializedString = ConvertByteArray2Str(memoryStream.ToArray()); TestClass xmlDomain = (TestClass)DeserializeObject(xmlSerializedString); Console.WriteLine(xmlDomain.TestFunction().ToString()); Console.ReadLine(); }