Ce code produit une FileNotFoundException, mais s'exécute finalement sans problème:
void ReadXml()
{
XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
//...
}
Voici l'exception:
Une exception de première chance de type 'System.IO.FileNotFoundException' s'est produite dans mscorlib.dll
Informations supplémentaires: Impossible de charger le fichier ou l'assembly 'MyAssembly.XmlSerializers, Version = 1.4.3190.15950, Culture = neutral, PublicKeyToken = null' ou l'une de ses dépendances. Le système ne peut pas trouver le fichier spécifié.
Il semble que le framework génère automatiquement l'assembly de sérialisation s'il n'est pas trouvé. Je peux le générer manuellement à l'aide de sgen.exe, ce qui atténue l'exception.
Comment obtenir Visual Studio pour générer automatiquement l'assembly de sérialisation XML?
Mise à jour: le paramètre Generate Serialization Assembly: On ne semble rien faire.
Voici comment j'ai réussi à le faire en modifiant le script MSBUILD dans mon fichier .CSPROJ:
Tout d'abord, ouvrez votre fichier .CSPROJ en tant que fichier plutôt qu'en tant que projet. Faites défiler vers le bas du fichier jusqu'à ce que vous trouviez ce code commenté, juste avant la fermeture de la balise Project:
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
Maintenant, nous insérons simplement notre propre cible AfterBuild pour supprimer tout XmlSerializer et SGen existant, comme ceci:
<Target Name="AfterBuild" DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)" Outputs="$(OutputPath)$(_SGenDllName)">
<!-- Delete the file because I can't figure out how to force the SGen task. -->
<Delete
Files="$(TargetDir)$(TargetName).XmlSerializers.dll"
ContinueOnError="true" />
<SGen
BuildAssemblyName="$(TargetFileName)"
BuildAssemblyPath="$(OutputPath)"
References="@(ReferencePath)"
ShouldGenerateSerializer="true"
UseProxyTypes="false"
KeyContainer="$(KeyContainerName)"
KeyFile="$(KeyOriginatorFile)"
DelaySign="$(DelaySign)"
ToolPath="$(TargetFrameworkSDKToolsDirectory)"
Platform="$(Platform)">
<Output
TaskParameter="SerializationAssembly"
ItemName="SerializationAssembly" />
</SGen>
</Target>
Ça marche pour moi.
Comme Martin l'a expliqué dans sa réponse , l'activation de la génération de l'assembly de sérialisation via les propriétés du projet n'est pas suffisante car la tâche SGen ajoute le /proxytypes
basculez vers la ligne de commande sgen.exe.
Microsoft a un propriété MSBuild documentée qui vous permet de désactiver le /proxytypes
bascule et provoque la tâche SGen pour générer les assemblys de sérialisation même s'il n'y a aucun type de proxy dans l'assembly.
SGenUseProxyTypes
Valeur booléenne qui indique si les types de proxy doivent être générés par SGen.exe. La cible SGen utilise cette propriété pour définir l'indicateur UseProxyTypes. Cette propriété est définie par défaut sur true et aucune interface utilisateur ne permet de modifier cela. Pour générer l'assembly de sérialisation pour les types non Webservice, ajoutez cette propriété au fichier de projet et définissez-la sur false avant d'importer Microsoft.Common.Targets ou C #/VB.targets
Comme la documentation le suggère, vous devez modifier votre fichier de projet à la main, mais vous pouvez ajouter la propriété SGenUseProxyTypes
à votre configuration pour activer la génération. La configuration de vos fichiers de projet finirait par ressembler à ceci:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<!-- Snip... -->
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
<SGenUseProxyTypes>false</SGenUseProxyTypes>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<!-- Snip... -->
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
<SGenUseProxyTypes>false</SGenUseProxyTypes>
</PropertyGroup>
Les autres réponses à cette question ont déjà mentionné le paramètre Propriétés du projet -> Construire -> Générer les assemblys de sérialisation mais par défaut, cela ne générera l'assembly que s'il y a sont " types de proxy de service Web XML " dans le projet.
La meilleure façon de comprendre le comportement exact de Visual Studio consiste à examiner la cible GenerateSerializationAssemblies dans le C:\WINDOWS\Microsoft.NET\Framework\v2 .0.50727 ** Fichier Microsoft.Common.targets **.
Vous pouvez vérifier le résultat de cette tâche de génération à partir de la fenêtre Visual Studio Output et sélectionner Build dans le Afficher la sortie de : liste déroulante. Vous devriez voir quelque chose comme
C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin\sgen.exe /Assembly:D:\Temp\LibraryA\obj\Debug\LibraryA.dll/ proxytypes /reference: ../compilateur:/delayign- LibraryA -> D:\Temp\LibraryA\bin\Debug\LibraryA.dll
Le point clé ici est le commutateur/ proxytypes . Vous pouvez lire sur les différents commutateurs pour XML Serializer Generator Tool (Sgen.exe)
Si vous connaissez MSBuild, vous pouvez personnaliser la cible GenerateSerializationAssemblies afin que la tâche SGen ait un attribut UseProxyTypes = "false" au lieu de true, mais vous devez alors assumer toutes les responsabilités associées de personnalisation du système Visual Studio/MSBuild. Alternativement, vous pouvez simplement étendre votre processus de génération pour appeler manuellement SGen sans le commutateur/proxytypes.
Si vous lisez la documentation de SGen, il est assez clair que Microsoft voulait limiter l'utilisation de cette fonctionnalité. Compte tenu de la quantité de bruit sur ce sujet, il est assez clair que Microsoft n'a pas fait un excellent travail avec la documentation de l'expérience Visual Studio. Il existe même un élément Connect Feedback pour ce problème et la réponse n'est pas excellente.
la création d'une nouvelle définition de tâche sgen brise une volée sur le volant. il suffit de définir les variables nécessaires pour que la tâche fonctionne comme prévu. Quoi qu'il en soit, la documentation Microsoft manque d'informations importantes.
(avec des pièces de http://msdn.Microsoft.com/en-us/library/ff798449.aspx )
Dans le fichier .csproj, immédiatement après l'élément <TargetFrameworkVersion>v?.?</TargetFrameworkVersion>
, Ajoutez les éléments suivants:
<SGenUseProxyTypes>false</SGenUseProxyTypes>
<SGenPlatformTarget>$(Platform)</SGenPlatformTarget>
Dans le fichier .csproj, dans chaque configuration de plateforme
par exemple. <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
ajoutez la ligne suivante:
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
Enregistrez et fermez le fichier .csproj.
Cette procédure génère un assembly supplémentaire nommé .xmlSerializers.dll dans votre dossier de sortie. Vous devrez déployer cet assembly avec votre solution.
SGen par défaut uniquement pour les types de proxy génère pour "Any CPU". Cela se produit si vous ne définissez pas les variables correspondantes dans votre fichier de projet.
SGenPlatformTarget est requis pour correspondre à votre PlatformTarget. J'ai tendance à penser que c'est un bug dans le modèle de projet. Pourquoi la plateforme cible sgen devrait-elle différer de celle de votre projet? Si c'est le cas, vous obtiendrez une exception d'exécution
0x80131040: la définition du manifeste de l'assembly localisé ne correspond pas à la référence de l'assembly
Vous pouvez localiser la définition de tâche msbuild en analysant votre fichier de projet:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
où MSBuildToolsPath dépend de votre <TargetFrameworkVersion>
http://msdn.Microsoft.com/en-us/library/bb397428.aspx
Regardez à l'intérieur de la définition de tâche SGen pour TargetFrameworkVersion 4.0 à partir de
Chemin d'installation de Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.CSharp.targets
pour voir les variables non documentées comme $ (SGenPlatformTarget) que vous êtes libre de définir dans votre fichier de projet
<Target
Name="GenerateSerializationAssemblies"
Condition="'$(_SGenGenerateSerializationAssembliesConfig)' == 'On' or ('@(WebReferenceUrl)'!='' and '$(_SGenGenerateSerializationAssembliesConfig)' == 'Auto')"
DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource"
Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)"
Outputs="$(IntermediateOutputPath)$(_SGenDllName)">
<SGen
BuildAssemblyName="$(TargetFileName)"
BuildAssemblyPath="$(IntermediateOutputPath)"
References="@(ReferencePath)"
ShouldGenerateSerializer="$(SGenShouldGenerateSerializer)"
UseProxyTypes="$(SGenUseProxyTypes)"
KeyContainer="$(KeyContainerName)"
KeyFile="$(KeyOriginatorFile)"
DelaySign="$(DelaySign)"
ToolPath="$(SGenToolPath)"
SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
EnvironmentVariables="$(SGenEnvironment)"
SerializationAssembly="$(IntermediateOutputPath)$(_SGenDllName)"
Platform="$(SGenPlatformTarget)"
Types="$(SGenSerializationTypes)">
<Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly"/>
</SGen>
</Target>
Je suis un peu en retard à la fête, mais j'ai trouvé la réponse précédente difficile à travailler. Plus précisément, Visual Studio plantait chaque fois que j'essayais d'afficher les propriétés de mon projet. Je suppose que cela est dû au fait qu'il ne comprenait plus comment lire le fichier csproj. Cela dit...
Ajoutez ce qui suit à votre ligne de commande d'événement post-build:
"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sgen.exe" "$(TargetPath)" /force
Cela exploitera sgen.exe directement pour reconstruire l'assembly de sérialisation Xml chaque fois que vous générez votre projet pour le débogage ou la version.
Au cas où quelqu'un d'autre rencontrerait ce problème soudainement après que tout fonctionnait bien avant: Pour moi, cela avait à voir avec la case à cocher "Activer juste mon code (géré uniquement)" décochée dans le menu des options (Options -> Débogage) (qui était s'éteint automatiquement après l'installation de .NET Reflector).
EDIT: Ce qui veut dire, bien sûr, que cette exception se produisait auparavant, mais lorsque "activer uniquement mon code" est désactivé, l'assistant de débogage (s'il est activé), s'arrêtera à ce point lorsqu'il sera lancé.
Regardez dans les propriétés de la solution. Sur l'onglet de construction en bas, il y a une liste déroulante appelée "Générer l'assemblage de sérialisation"
Une solution légèrement différente de celle fournie par brain backup pourrait être de spécifier directement la cible de la plateforme là où vous devez l'utiliser comme ceci:
<!-- Check the platform target value and if present use that for a correct *.XmlSerializer.dll platform setup (default is MSIL)-->
<PropertyGroup Condition=" '$(PlatformTarget)'=='' ">
<SGenPlatform>$(Platform)</SGenPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(PlatformTarget)'!='' ">
<SGenPlatform>$(PlatformTarget)</SGenPlatform>
</PropertyGroup>
<!-- Delete the file because I can't figure out how to force the SGen task. -->
<Delete Files="$(TargetDir)$(TargetName).XmlSerializers.dll" ContinueOnError="true" />
<SGen
BuildAssemblyName="$(TargetFileName)"
BuildAssemblyPath="$(OutputPath)"
References="@(ReferencePath)"
ShouldGenerateSerializer="true"
UseProxyTypes="false"
KeyContainer="$(KeyContainerName)"
KeyFile="$(KeyOriginatorFile)"
DelaySign="$(DelaySign)"
ToolPath="$(SGenToolPath)"
SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
EnvironmentVariables="$(SGenEnvironment)"
Platform="$(SGenPlatform)">
<Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
</SGen>