Une application avec laquelle je travaille échoue lorsque j'essaie de sérialiser des types.
Une déclaration comme
XmlSerializer lizer = new XmlSerializer(typeof(MyType));
produit:
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)
Je ne définis aucun sérialiseur spécial pour ma classe.
Comment puis-je résoudre ce problème?
c#
xml-serialization
Irwin
la source
la source
Generate serialization assembly
menu déroulant sur "On", au lieu de "Auto".Réponses:
Croyez-le ou non, c'est un comportement normal. Une exception est levée mais gérée par XmlSerializer, donc si vous l'ignorez, tout devrait bien continuer.
J'ai trouvé cela très ennuyeux, et il y a eu de nombreuses plaintes à ce sujet si vous recherchez un peu, mais d'après ce que j'ai lu, Microsoft n'a pas l'intention de faire quoi que ce soit à ce sujet.
Vous pouvez éviter d'obtenir des fenêtres contextuelles d'exception tout le temps lors du débogage si vous désactivez les exceptions de première chance pour cette exception spécifique. Dans Visual Studio, accédez à Debug -> Exceptions (ou appuyez sur Ctrl+ Alt+ E), Common Language Runtime Exceptions -> System.IO -> System.IO.FileNotFoundException .
Vous pouvez trouver des informations sur un autre moyen de le contourner dans l' exception de blog C # XmlSerializer FileNotFound (qui traite de l'outil XmlSerializerPreCompiler de Chris Sells ).
la source
Comme Martin Sherburn l'a dit, c'est un comportement normal. Le constructeur de XmlSerializer essaie d'abord de trouver un assembly nommé [YourAssembly] .XmlSerializers.dll qui doit contenir la classe générée pour la sérialisation de votre type. Puisqu'une telle DLL n'a pas encore été générée (elles ne le sont pas par défaut), une FileNotFoundException est levée. Lorsque cela se produit, le constructeur de XmlSerializer intercepte cette exception et la DLL est générée automatiquement au moment de l'exécution par le constructeur de XmlSerializer (cela se fait en générant des fichiers source C # dans le répertoire% temp% de votre ordinateur, puis en les compilant à l'aide du compilateur C #). Les constructions supplémentaires d'un XmlSerializer pour le même type utiliseront simplement la DLL déjà générée.
L'exception est gérée par le constructeur de XmlSerializer. Il n'est pas nécessaire de faire quoi que ce soit vous-même, vous pouvez simplement cliquer sur «Continuer» (F5) pour continuer à exécuter votre programme et tout ira bien. Si vous êtes gêné par les exceptions arrêtant l'exécution de votre programme et faisant apparaître un assistant d'exception, vous avez soit 'Just My Code' désactivé, soit vous avez défini FileNotFoundException pour interrompre l'exécution lorsqu'il est lancé, au lieu de quand 'User- non géré ».
Pour activer «Just My Code», accédez à Outils >> Options >> Débogage >> Général >> Activer Just My Code. Pour désactiver la rupture d'exécution lorsque FileNotFound est levé, accédez à Debug >> Exceptions >> Find >> entrez 'FileNotFoundException' >> décochez la case 'Thrown' de System.IO.FileNotFoundException.
la source
FileNotFoundException
sera lancé. La différence n'est pas dans la façon dont l'existence de l'assembly est vérifiée, mais dans la façon de le générer une fois qu'il est déterminé qu'il est manquant. Avant, il utilisait la génération de code C # textuel avec un appel au compilateur C # pour créer l'IL. À partir de .NET 4.5, il émet IL directement, sans utiliser de compilateur.File.Exists()
peut ne pas être suffisant. La localisation d'un assembly n'est pas une affaire simple, le runtime regarde à plusieurs endroits et je crois que le comportement change en fonction de l'environnement (application console vs hébergée dans IIS, etc.). Je suppose que ce qui aurait dû être mis en œuvre était unTryLoadAssembly()
ou quelque chose de similaire.Dans les propriétés du projet Visual Studio (page "Build", si je me souviens bien), il y a une option disant "générer un assemblage de sérialisation". Essayez de l'activer pour un projet qui génère [Assemblage contenant de MyType] .
la source
Il existe une solution pour cela. Si tu utilises
il devrait éviter cette exception. Cela a fonctionné pour moi.
AVERTISSEMENT: ne pas utiliser plusieurs fois, ou vous aurez une fuite de mémoire
Vous perdrez de la mémoire comme un fou si vous utilisez cette méthode pour créer des instances de
XmlSerializer
même type!En effet, cette méthode contourne la mise en cache intégrée à condition que le
XmlSerializer(type)
etXmlSerializer(type, defaultNameSpace)
constructeurs (tous les autres constructeurs contournent également le cache).Si vous utilisez une méthode pour créer un XmlSerializer qui n'est pas via ces deux constructeurs, vous devez implémenter votre propre mise en cache ou vous aurez une mémoire d'hémorragie.
la source
XmlSerializer
même type! Cela est dû au fait que cette méthode contourne la mise en cache intégrée à condition que les constructeursXmlSerializer(type)
etXmlSerializer(type, defaultNameSpace)
(tous les autres constructeurs contournent également le cache). Si vous utilisez une méthode pour créer unXmlSerializer
qui ne passe pas par ces deux constructeurs, vous devez implémenter votre propre mise en cache ou vous aurez une mémoire d'hémorragie.FromTypes
semble remplir le cache. Donc, cela devrait être un moyen valide de réchauffer unXmlSerializer
cache vide dans une instruction (comme le suggère l'article), mais un très mauvais moyen d'en récupérer quoi que ce soit (ne doit être fait que via les constructeurs les plus simples). En tout cas, je ne savais pas que c'était un bug, j'ai toujours pensé que tout ce qui fuit est censé fuir (comme lesXmlSerializer
constructeurs les plus avancés ). Je n'aurais même pas pensé à utiliserFromTypes()
car vous pouvez le fairetypes.Select(t => new XmlSerializer(t))
.FromTypes
a son attrait - même si les exceptions levées sont toutes interceptées, c'est une opération coûteuse; l'approche «cache à votre façon» semble être la seule solution de contournement, car le seul correctif officiellement pris en charge semble être dans un assemblage Web obscur. (modifier: franchement, je suis tout pour tout porter sur les contrats de données :))J'ai rencontré ce problème exact et je n'ai pu le contourner par aucune des solutions mentionnées.
Puis j'ai finalement trouvé une solution. Il semble que le sérialiseur ait besoin non seulement du type, mais également des types imbriqués. Changer ceci:
Pour ça:
Correction du problème pour moi. Plus d'exceptions ou quoi que ce soit.
la source
var xmlSerializer = new XmlSerializer(typeof(T), typeof(T).GetNestedTypes());
Ma solution est d'aller directement à la réflexion pour créer le sérialiseur. Cela contourne l'étrange chargement de fichier qui provoque l'exception. J'ai empaqueté ceci dans une fonction d'aide qui s'occupe également de la mise en cache du sérialiseur.
la source
Pour éviter l'exception, vous devez faire deux choses:
Ajoutez l'attribut System.Xml.Serialization.XmlSerializerAssembly à votre classe. Remplacez «MyAssembly» par le nom de l'assembly dans lequel se trouve MyClass.
Générez le fichier de sérialisation à l'aide de l'utilitaire sgen.exe et déployez-le avec l'assembly de la classe.
'sgen.exe MyAssembly.dll' générera le fichier MyAssembly.XmlSerializers.dll
Ces deux modifications feront que le .net trouvera directement l'assembly. Je l'ai vérifié et cela fonctionne sur .NET Framework 3.5 avec Visual Studio 2008
la source
Cette exception peut également être interceptée par un assistant de débogage géré (MDA) appelé BindingFailure.
Ce MDA est utile si votre application est conçue pour être livrée avec des assemblys de sérialisation pré-génération. Nous faisons cela pour augmenter les performances de notre application. Cela nous permet de nous assurer que les assemblys de sérialisation pré-construits sont correctement construits par notre processus de construction et chargés par l'application sans être reconstruits à la volée.
Ce n'est vraiment pas utile sauf dans ce scénario, car comme d'autres affiches l'ont dit, lorsqu'une erreur de liaison est interceptée par le constructeur Serializer, l'assembly de sérialisation est reconstruit au moment de l'exécution. Vous pouvez donc généralement le désactiver.
la source
La fonction XmlSerializer.FromTypes ne lève pas l'exception, mais elle fuit la mémoire. C'est pourquoi vous devez mettre en cache un tel sérialiseur pour chaque type afin d'éviter une fuite de mémoire pour chaque instance créée.
Créez votre propre fabrique XmlSerializer et utilisez-la simplement:
L'usine ressemble à:
Version plus compliquée sans possibilité de fuite de mémoire (veuillez consulter le code):
la source
Le dépannage des erreurs de compilation est en revanche très compliqué. Ces problèmes se manifestent dans une FileNotFoundException avec le message:
Vous vous demandez peut-être ce qu'une exception de fichier introuvable a à voir avec l'instanciation d'un objet sérialiseur, mais n'oubliez pas: le constructeur écrit des fichiers C # et essaie de les compiler. La pile d'appels de cette exception fournit de bonnes informations pour étayer cette suspicion. L'exception s'est produite alors que XmlSerializer a tenté de charger un assembly généré par CodeDOM appelant la méthode System.Reflection.Assembly.Load. L'exception ne fournit pas d'explication sur la raison pour laquelle l'assembly que le XmlSerializer était censé créer n'était pas présent. En général, l'assembly n'est pas présent car la compilation a échoué, ce qui peut se produire car, dans de rares circonstances, les attributs de sérialisation produisent du code que le compilateur C # ne parvient pas à compiler.
Remarque Cette erreur se produit également lorsque le XmlSerializer s'exécute sous un compte ou un environnement de sécurité qui n'est pas en mesure d'accéder au répertoire temporaire.
Source : http://msdn.microsoft.com/en-us/library/aa302290.aspx
la source
Dans les propriétés du projet Visual Studio, il existe une option indiquant «générer un assembly de sérialisation». Essayez de l'activer pour un projet qui génère [Assemblage contenant de MyType].
la source
Une classe personnalisée à sérialiser:
J'ai joint l'extrait de code. Peut-être que cela peut vous aider.
la source
J'avais un problème similaire et ignorer l'exception ne fonctionnait pas pour moi. Mon code appelait la configuration de NServiceBus
Configure.With(...).XmlSerializer()...
Ce qui m'a permis de changer la plateforme de mon projet.
la source
Juste comme référence. Prenant de la réponse et des commentaires de DB, je suis venu avec cette solution qui est proche de la solution DB. Cela fonctionne bien dans tous mes cas et il est sûr pour les threads. Je ne pense pas que l'utilisation d'un ConcurrentDictionary aurait été acceptable.
Usage:
la source
Votre type peut référencer d'autres assemblys qui ne peuvent être trouvés ni dans le GAC ni dans votre dossier bin local ==> ...
Pouvez-vous donner un exemple du type que vous souhaitez sérialiser?
Remarque: assurez-vous que votre type implémente Sérialisable.
la source
J'obtenais la même erreur, et c'était dû au type que j'essayais de désérialiser de ne pas avoir de constructeur sans paramètre par défaut . J'ai ajouté un constructeur et il a commencé à fonctionner.
la source
J'ai eu le même problème jusqu'à ce que j'utilise un outil tiers pour générer la classe à partir du XSD et cela a fonctionné! J'ai découvert que l'outil ajoutait du code supplémentaire en haut de ma classe. Lorsque j'ai ajouté ce même code en haut de ma classe d'origine, cela a fonctionné. Voici ce que j'ai ajouté ...
la source
Vu beaucoup de recommandations à utiliser
ConcurrentDictionary
, mais pas d'exemples solides, donc je vais jeter mon chapeau dans cette course aux solutions. Je ne suis pas un développeur thread-safe, donc si ce code n'est pas solide, veuillez parler pour ceux qui suivront.J'ai vu d'autres articles impliquer
ConcurrentDictionary
etLazy
charger la valeur. Je ne sais pas si c'est pertinent ici ou non, mais voici le code pour cela:la source