sharp serialize serializar example deserialize deserializar c# xml xml-serialization

serializar - serialize object c#



Generar un ensamblado de serializaciĆ³n Xml como parte de mi compilaciĆ³n (8)

Este código produce una excepción FileNotFoundException, pero finalmente se ejecuta sin problemas:

void ReadXml() { XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); //... }

Aquí está la excepción:

Se produjo una excepción de primera oportunidad del tipo ''System.IO.FileNotFoundException'' en mscorlib.dll

Información adicional: No se pudo cargar el archivo o ensamblado ''MyAssembly.XmlSerializers, Version = 1.4.3190.15950, Culture = neutral, PublicKeyToken = null'' o una de sus dependencias. El sistema no puede encontrar el archivo especificado.

Parece que el marco genera automáticamente el conjunto de serialización si no se encuentra. Puedo generarlo manualmente con sgen.exe, lo que alivia la excepción.

¿Cómo obtengo Visual Studio para generar el ensamblado de serialización XML automáticamente?

Actualización: Generate Serialization Assembly: en la configuración no parece hacer nada.


Así es como logré hacerlo modificando el script MSBUILD en mi archivo .CSPROJ:

Primero, abra su archivo .CSPROJ como un archivo en lugar de como un proyecto. Desplácese hasta la parte inferior del archivo hasta que encuentre este código comentado, justo antes del cierre de la etiqueta del Proyecto:

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

Ahora solo insertamos nuestro propio objetivo AfterBuild para eliminar cualquier nuestro XmlSerializer existente y nuestro propio SGen, así:

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

Funciona para mi.


Como Martin ha explicado en su respuesta , activar la generación del conjunto de serialización mediante las propiedades del proyecto no es suficiente porque la tarea SGen agrega el /proxytypes a la línea de comando sgen.exe.

Microsoft tiene una propiedad MSBuild documentada que le permite desactivar el /proxytypes y hace que la tarea SGen genere los ensamblados de serialización incluso si no hay ningún tipo de proxy en el ensamblado.

SGenUseProxyTypes

Un valor booleano que indica si los tipos de proxy deberían ser generados por SGen.exe. El objetivo SGen usa esta propiedad para establecer el indicador UseProxyTypes. Esta propiedad se establece de forma predeterminada en true, y no hay UI para cambiar esto. Para generar el ensamblaje de serialización para tipos de servicio que no sean web, agregue esta propiedad al archivo de proyecto y establézcalo en falso antes de importar el Microsoft.Common.Targets o el C # / VB.targets

Como la documentación sugiere, debe modificar su archivo de proyecto a mano, pero puede agregar la propiedad SGenUseProxyTypes a su configuración para habilitar la generación. La configuración de tus archivos de proyecto terminaría luciendo algo como esto:

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


En caso de que alguien más se encuentre con este problema de repente después de que todo funcionara bien antes: Para mí, tenía que ver con la casilla "Habilitar solo mi código (solo administrado)" desmarcada en el menú de opciones (Opciones -> Depuración) (que era se apaga automáticamente después de instalar .NET Reflector).

EDITAR: Lo que quiere decir, por supuesto, que esta excepción estaba sucediendo antes, pero cuando "habilitar solo mi código" está desactivado, el asistente de depuración (si está habilitado) se detendrá en este momento cuando se lanza.


Las otras respuestas a esta pregunta ya han mencionado la configuración de Project Properties-> Build-> Generate Serialization Assemblies pero, por defecto, esto solo generará el ensamblado si hay " tipos de proxy de servicio web XML " en el proyecto.

La mejor manera de comprender el comportamiento exacto de Visual Studio es examinar el destino GenerateSerializationAssemblies dentro del archivo C: / WINDOWS / Microsoft.NET / Framework / v2.0.50727 ** Microsoft.Common.targets **.

Puede verificar el resultado de esta tarea de compilación desde la ventana Visual Studio Output y seleccionar Build en el cuadro desplegable Mostrar resultados desde :. Deberías ver algo en la línea de

C: / Archivos de programa / Microsoft Visual Studio 8 / SDK / v2.0 / bin / sgen.exe /assembly:D:/Temp/LibraryA/obj/Debug/LibraryA.dll / proxytypes / reference: .. / compilador: / delaysign- LibraryA -> D: / Temp / LibraryA / bin / Debug / LibraryA.dll

El punto clave aquí es el modificador / proxytypes . Puede leer sobre los diversos modificadores para la herramienta Generador de serializadores XML (Sgen.exe)

Si está familiarizado con MSBuild, puede personalizar el objetivo GenerateSerializationAssemblies para que la tarea SGen tenga un atributo de UseProxyTypes = "false" en lugar de verdadero, pero luego debe tener en cuenta toda la responsabilidad asociada de personalizar el sistema Visual Studio / MSBuild. Alternativamente, podría extender su proceso de compilación para llamar a SGen manualmente sin el modificador / proxytypes.

Si lee la documentación de SGen, está bastante claro que Microsoft quería limitar el uso de esta instalación. Dada la cantidad de ruido sobre este tema, está bastante claro que Microsoft no hizo un gran trabajo documentando la experiencia de Visual Studio. Incluso hay un elemento de Connect Feedback para este problema y la respuesta no es excelente.


Llego un poco tarde a la fiesta, pero la respuesta anterior me resultó difícil de trabajar. Específicamente, Visual Studio se bloqueaba cada vez que intentaba ver las propiedades de mi proyecto. Me imagino que esto se debió al hecho de que ya no entendía cómo leer el archivo csproj. Eso dijo ...

Agregue lo siguiente a su línea de comando de evento posterior a la compilación:

"C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Bin/NETFX 4.0 Tools/sgen.exe" "$(TargetPath)" /force

Esto aprovechará sgen.exe directamente para reconstruir el conjunto de serialización Xml cada vez que construya su proyecto para depurar o liberar.


Mire en las propiedades de la solución. En la pestaña de compilación en la parte inferior hay un menú desplegable llamado "Generar ensamblaje de serialización"


Una solución ligeramente diferente a la proporcionada por share podría ser especificar directamente el objetivo de la plataforma donde debe usarlo así:

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


crear una nueva definición de tarea sgen rompe una mosca en la rueda. simplemente configure las variables necesarias para que la tarea funcione como se esperaba. De todos modos, la documentación de Microsoft carece de información importante.

Pasos para pregenerar conjuntos de serialización

(con partes de http://msdn.microsoft.com/en-us/library/ff798449.aspx )

  1. En Visual Studio 2010, en el Explorador de soluciones, haga clic con el botón derecho en el proyecto para el que desea generar conjuntos de serialización y luego haga clic en Descargar proyecto.
  2. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto para el que desea generar conjuntos de serialización y luego haga clic en Editar .csproj.
  3. En el archivo .csproj, inmediatamente después del elemento <TargetFrameworkVersion>v?.?</TargetFrameworkVersion> , agregue los siguientes elementos:

    <SGenUseProxyTypes>false</SGenUseProxyTypes> <SGenPlatformTarget>$(Platform)</SGenPlatformTarget>

  4. En el archivo .csproj, en cada configuración de plataforma

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

    agregue la siguiente línea:

    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>

  5. Guarde y cierre el archivo .csproj.

  6. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto que acaba de editar y luego haga clic en Recargar proyecto.

Este procedimiento genera un ensamblado adicional llamado .xmlSerializers.dll en su carpeta de salida. Tendrá que implementar este ensamblaje con su solución.

Explicación

SGen por defecto solo para los tipos de proxy genera para "Cualquier CPU". Esto sucede si no establece las variables correspondientes en su archivo de proyecto.

SGenPlatformTarget es necesario para que coincida con su PlatformTarget. Tiendo a pensar que esto es un error en la plantilla del proyecto. ¿Por qué la plataforma de destino sgen debe ser diferente a la de su proyecto? Si lo hace, obtendrá una excepción de tiempo de ejecución

0x80131040: la definición de manifiesto del conjunto ubicado no coincide con la referencia de ensamblaje

Puede ubicar la definición de la tarea msbuild analizando su archivo de proyecto:

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

donde MSBuildToolsPath depende de su <TargetFrameworkVersion> http://msdn.microsoft.com/en-us/library/bb397428.aspx

Mire dentro de la definición de la tarea SGen para TargetFrameworkVersion 4.0 desde

Ruta de instalación de Windows / Microsoft.NET / Framework / v4.0.30319 / Microsoft.CSharp.targets

para ver las variables no documentadas como $ (SGenPlatformTarget) que puede configurar libremente en su archivo de proyecto

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