64 votes

Générer un assemblage de sérialisation Xml dans le cadre de ma construction

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'assemblage 'MyAssembly.XmlSerializers, Version=1.4.3190.15950, Culture=neutral, PublicKeyToken=null' ou l'une de ses dépendances. Le système ne trouve pas le fichier spécifié.


Il semble que le framework génère automatiquement l'assemblage de sérialisation s'il n'est pas trouvé. Je peux le générer manuellement en utilisant sgen.exe, ce qui atténue l'exception.

Comment faire pour que Visual Studio génère automatiquement l'assemblage de sérialisation XML ?


Mise à jour : le paramètre Generate Serialization Assembly : On ne semble pas avoir d'effet.

67voto

heavyd Points 8845

Comme Martin l'a expliqué dans sa réponse l'activation de la génération de l'assemblage de sérialisation par le biais des propriétés du projet n'est pas suffisante car la tâche SGen ajoute l'assemblage de sérialisation à l'assemblage de sérialisation. /proxytypes passer à la ligne de commande sgen.exe.

Microsoft a un Propriété MSBuild documentée qui vous permet de désactiver le /proxytypes et fait en sorte que la tâche SGen génère les assemblages de sérialisation même si l'assemblage ne contient aucun type de proxy.

SGenUseProxyTypes

Une 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. La valeur par défaut de cette propriété est true. et il n'existe pas d'interface utilisateur pour la modifier. Pour générer l'assemblage de sérialisation pour pour les types de services non Web, ajoutez cette propriété au fichier de projet et définissez-la à false avant d'importer le fichier de projet. à false avant d'importer le fichier Microsoft.Common.Targets ou le fichier C#/VB.targets

Comme le suggère la documentation, vous devez modifier votre fichier de projet à la main, mais vous pouvez ajouter l'option SGenUseProxyTypes à votre configuration pour permettre la génération. La configuration de vos fichiers de projet devrait ressembler à quelque chose comme 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>

56voto

flipdoubt Points 4140

Voici comment j'ai réussi à le faire en modifiant le MSBUILD script dans mon fichier .CSPROJ :

Tout d'abord, ouvrez votre fichier .CSPROJ comme un fichier plutôt que comme un projet. Faites défiler vers le bas du fichier jusqu'à ce que vous trouviez ce code commenté, juste avant la fin 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, il suffit d'insérer notre propre cible AfterBuild pour supprimer tout XmlSerializer existant et SGen notre propre, comme suit :

<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.

28voto

Les autres réponses à cette question ont déjà mentionné les Propriétés du projet->Construire->Construire. Générer des assemblages de sérialisation mais par défaut, cela ne génère l'assemblage que s'il y a des " Types de proxy de services Web XML " dans le projet.

Le meilleur moyen de comprendre le comportement exact de Visual Studio est d'examiner le fichier GenerateSerializationAssemblies dans le cadre de la C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 Fichier **Microsoft.Common.targets**.

Vous pouvez vérifier le résultat de cette tâche de construction à partir de la fenêtre Visual Studio Sortie et sélectionnez Construire de la Montrer la sortie de : boîte déroulante. Vous devriez voir quelque chose du type

C:\Program Fichiers \Microsoft Visual Studio 8 \SDK\v2.0\bin\sgen.exe /assemblage : D:\Temp\LibraryA\obj\Debug\LibraryA.dll / proxytypes /référence :.. /compilateur:/delaysign- BibliothèqueA -> D:\Temp\LibraryA\bin\Debug\LibraryA.dll

Le point clé ici est le / proxytypes interrupteur. Vous pouvez vous renseigner sur les différents commutateurs pour le Outil de génération de sérialiseur XML (Sgen.exe)

Si vous êtes familier avec MSBuild, vous pouvez personnaliser la cible GenerateSerializationAssemblies pour que la tâche SGen ait un attribut UseProxyTypes="false" au lieu de true mais mais vous devrez alors assumer toutes les responsabilités associées à la personnalisation du système Visual Studio / MSBuild. Vous pouvez également étendre votre processus de construction pour appeler SGen manuellement sans le commutateur /proxytypes.

Si vous lisez la documentation de SGen, il est assez clair que Microsoft voulait limiter l'utilisation de cette fonction. Compte tenu de la quantité de bruit sur ce sujet, il est assez clair que Microsoft n'a pas fait un excellent travail de documentation de l'expérience Visual Studio. Il y a même un Connecter les commentaires pour cette question et la réponse n'est pas très bonne.

9voto

brain backup Points 51

La création d'une nouvelle définition de tâche sgen casse une mouche sur la roue. Il suffit de définir les variables nécessaires pour que la tâche fonctionne comme prévu. De toute façon, la documentation de Microsoft manque d'informations importantes.

Étapes pour pré-générer des assemblages de sérialisation

(avec des parties de http://msdn.microsoft.com/en-us/library/ff798449.aspx )

  1. Dans Visual Studio 2010, dans l'Explorateur de solutions, cliquez avec le bouton droit de la souris sur le projet pour lequel vous souhaitez générer des assemblages de sérialisation, puis cliquez sur Décharger le projet.

  2. Dans l'Explorateur de solutions, cliquez avec le bouton droit de la souris sur le projet pour lequel vous souhaitez générer des assemblages de sérialisation, puis cliquez sur Modifier .csproj.

  3. 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>

  4. Dans le fichier .csproj, dans chaque configuration de plateforme

    par exemple <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">

    ajoutez la ligne suivante :

    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>

  5. Enregistrez et fermez le fichier .csproj.

  6. Dans l'explorateur de solutions, cliquez à droite sur le projet que vous venez de modifier, puis cliquez sur Recharger le projet.

Cette procédure génère un assemblage supplémentaire nommé .xmlSerializers.dll dans votre dossier de sortie. Vous devrez déployer cet assemblage avec votre solution.


Explication

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 nécessaire pour correspondre à votre PlatformTarget. J'ai tendance à penser qu'il s'agit d'un bug dans le modèle de projet. Pourquoi la plateforme cible de sgen devrait-elle être différente 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'assemblage localisé ne correspond pas à la référence de l'assemblage.

Vous pouvez localiser la définition de la tâche msbuild en analysant votre fichier de projet :

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

où le MSBuildToolsPath dépend de votre <TargetFrameworkVersion> http://msdn.microsoft.com/en-us/library/bb397428.aspx

Regardez dans la définition de la tâche SGen pour TargetFrameworkVersion 4.0 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>

2voto

joniba Points 1010

Au cas où quelqu'un d'autre rencontrerait ce problème soudainement alors que tout fonctionnait bien auparavant : Pour moi, cela était dû au fait que la case "Activer seulement mon code (géré uniquement)" n'était pas cochée dans le menu des options (Options -> Débogage) (qui était automatiquement désactivée après l'installation de .NET Reflector).

EDIT : Ce qui veut dire, bien sûr, que cette exception se produisait avant, mais que lorsque l'option "activer seulement mon code" est désactivée, l'assistant de débogage (s'il est activé), s'arrête à ce moment-là lorsqu'il est lancé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X