Pregunta

Este código produce una 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 ensamblado de serialización si no se encuentra. puedo generarlo manualmente usando sgen.exe, lo que alivia la excepción.

¿Cómo hago para que Visual Studio genere el ensamblado de serialización XML automáticamente?


Actualización: La configuración Generar serialización: Activada no parece hacer nada.

¿Fue útil?

Solución

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 el final del archivo hasta que encuentre este código comentado, justo antes del cierre de la etiqueta 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 XmlSerializer existente y SGen el nuestro, 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>

Eso funciona para mí.

Otros consejos

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

Microsoft tiene una propiedad documentada de MSBuild que le permite deshabilitar la SGenUseProxyTypes cambia y hace que la tarea SGen genere los ensamblados de serialización incluso si no hay tipos de proxy en el ensamblaje.

  

SGenUseProxyTypes

     

Un valor booleano que indica si los tipos de proxy   debe ser generado por SGen.exe. El objetivo SGen utiliza esta propiedad para   establece la bandera UseProxyTypes. Esta propiedad por defecto es verdadera, y allí   No hay interfaz de usuario para cambiar esto. Para generar el ensamblado de serialización para   tipos que no son de servicio web, agregue esta propiedad al archivo del proyecto y configúrelo   a falso antes de importar 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 <=> a su configuración para permitir la generación. La configuración de los archivos de su proyecto terminaría pareciéndose a 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>

Las otras respuestas a esta pregunta ya han mencionado las propiedades del proyecto - > Build - > Generar conjuntos de serialización , pero por defecto esto solo generará el ensamblaje si existe son " 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 C: \ WINDOWS \ Microsoft.NET \ Framework \ v2.0.50727 ** Microsoft.Common. objetivos ** archivo.

Puede verificar el resultado de esta tarea de compilación desde la ventana Resultados de Visual Studio y seleccionar Compilar en el Mostrar resultados desde : desplegable caja. 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 / referencia: .. / compilador: / delaysign- BibliotecaA - & Gt; D: \ Temp \ LibraryA \ bin \ Debug \ LibraryA.dll

El punto clave aquí es el modificador / proxytypes . Puede leer sobre los diversos interruptores para la Herramienta de generador de serializador XML ( Sgen.exe)

Si está familiarizado con MSBuild, puede personalizar el destino GenerateSerializationAssemblies para que la tarea SGen tenga un atributo de UseProxyTypes = " false " en lugar de cierto pero entonces debe asumir 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 lees la documentación para SGen, son bastante claros 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 al documentar la experiencia de Visual Studio. Incluso hay un elemento Connect Connect para este problema y la respuesta no es genial.

crear una nueva definición de tarea sgen rompe una mosca en la rueda. solo configure las variables necesarias para que la tarea funcione según lo previsto. De todos modos, la documentación de Microsoft carece de información importante.

Pasos para pregenerar ensamblados 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 ensamblados 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 ensamblados 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

    p. <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 Volver a cargar proyecto.

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


Explicación

SGen por defecto solo para tipos de proxy genera para & # 8220; Cualquier CPU & # 8221 ;. Esto sucede si no configura las variables correspondientes en su archivo de proyecto.

Se requiere SGenPlatformTarget 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 difiere de la de su proyecto? Si lo hace, obtendrá una excepción de tiempo de ejecución

  

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

Puede localizar la definición de 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 tarea SGen para TargetFrameworkVersion 4.0 de

  

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>

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

EDITAR: Es decir, por supuesto, que esta excepción estaba ocurriendo antes, pero cuando & Quot; habilite solo mi código & Quot; está desactivado, el asistente de depuración (si está habilitado), se detendrá en este punto cuando se lance.

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

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 ensamblado de serialización Xml cada vez que cree su proyecto para depurar o liberar.

Busque en las propiedades de la solución. En la pestaña de compilación en la parte inferior hay un menú desplegable llamado & Quot; Generar el conjunto de serialización & Quot;

Una solución ligeramente diferente de la proporcionada por copia de seguridad del cerebro podría ser especificar directamente el objetivo de la plataforma justo donde tiene que usar así es:

<!-- 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>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top