Gerando um assembly de serialização Xml como parte da minha compilation

Esse código produz um FileNotFoundException, mas, no final, é executado sem problemas:

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

Aqui está a exceção:


Uma primeira chance exceção do tipo ‘System.IO.FileNotFoundException’ ocorreu em mscorlib.dll

Informações adicionais: Não foi possível carregar o arquivo ou assembly ‘MyAssembly.XmlSerializers, versão = 1.4.3190.15950, Culture = neutral, PublicKeyToken = null’ ou uma de suas dependencies. O sistema não pode encontrar o arquivo especificado.


Parece que a estrutura gera automaticamente a assembly de serialização, caso não seja encontrada. Eu posso gerá-lo manualmente usando o sgen.exe, o que alivia a exceção.

Como obtenho o visual studio para gerar o assembly de serialização XML automaticamente?


Atualização: O conjunto de serialização Gerar: na configuração não parece fazer nada.

Foi assim que consegui modificar o script MSBUILD no meu arquivo .CSPROJ:

Primeiro, abra seu arquivo .CSPROJ como um arquivo em vez de um projeto. Role até o final do arquivo até encontrar este código comentado, logo antes do fechamento da tag Project:

  

Agora, apenas inserimos nosso próprio destino AfterBuild para excluir qualquer XmlSerializer e SGen existentes, da seguinte forma:

        

Isso funciona para mim.

Como Martin explicou em sua resposta , ativar a geração do assembly de serialização através das propriedades do projeto não é suficiente porque a tarefa SGen está adicionando a opção /proxytypes à linha de comando sgen.exe.

Microsoft tem uma propriedade MSBuild documentada que permite que você desative a opção /proxytypes e faz com que a Tarefa SGen gere os assemblies de serialização mesmo se não houver nenhum tipo de proxy no assembly.

SGenUseProxyTypes

Um valor booleano que indica se os tipos de proxy devem ser gerados pelo SGen.exe. O destino SGen usa essa propriedade para definir o sinalizador UseProxyTypes. Essa propriedade é padronizada como true e não há interface do usuário para alterar isso. Para gerar o assembly de serialização para tipos de não-serviço da Web, inclua essa propriedade no arquivo de projeto e defina-a como false antes de importar o Microsoft.Common.Targets ou o C # / VB.targets

Como a documentação sugere, você deve modificar seu arquivo de projeto manualmente, mas pode adicionar a propriedade SGenUseProxyTypes à sua configuração para ativar a geração. Sua configuração de arquivos de projeto acabaria parecendo com isto:

    On false    On false  

As outras respostas a essa pergunta já mencionaram a configuração Propriedades do Projeto-> Construir-> Gerar Assemblies de Serialização , mas, por padrão, isso apenas gerará o assembly se houver ” tipos de proxy de serviço da Web XML ” no projeto.

A melhor maneira de entender o comportamento exato do Visual Studio é examinar o destino GenerateSerializationAssemblies no arquivo C: \ WINDOWS \ Microsoft.NET \ Framework \ v2.0.50727 ** Microsoft.Common.targets **.

Você pode verificar o resultado dessa tarefa de compilation na janela Saída do Visual Studio e selecionar Compilar na checkbox suspensa Mostrar a saída de :. Você deveria ver algo ao longo das linhas de

C: \ Arquivos de Programas \ 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

O ponto chave aqui é a opção / proxytypes . Você pode ler sobre as várias opções para a ferramenta Generator XML Serializer (Sgen.exe)

Se você estiver familiarizado com o MSBuild, poderá personalizar o destino GenerateSerializationAssemblies para que a tarefa SGen tenha um atributo de UseProxyTypes = “false” em vez de true, mas você precisará assumir toda a responsabilidade associada de personalizar o sistema Visual Studio / MSBuild. Como alternativa, você poderia apenas estender seu processo de compilation para chamar manualmente o SGen sem a opção / proxytypes.

Se você ler a documentação do SGen, eles ficarão bastante claros de que a Microsoft queria limitar o uso desse recurso. Dada a quantidade de ruído neste tópico, fica claro que a Microsoft não fez um ótimo trabalho ao documentar a experiência do Visual Studio. Existe até um item de Feedback do Connect para este problema e a resposta não é ótima.

Criando uma nova definição de tarefa sgen quebra uma mosca na roda. basta definir as variables ​​necessárias para que a tarefa funcione como pretendido. De qualquer forma a documentação da Microsoft não possui algumas informações importantes.

Etapas para pré-gerar assemblies de serialização

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

  1. No Visual Studio 2010, no Solution Explorer, clique com o botão direito do mouse no projeto para o qual você deseja gerar assemblies de serialização e, em seguida, clique em Unload Project.
  2. No Solution Explorer, clique com o botão direito do mouse no projeto para o qual você deseja gerar assemblies de serialização e, em seguida, clique em Editar .csproj.
  3. No arquivo .csproj, imediatamente após o elemento v?.? , inclua os seguintes elementos:

    false $(Platform)

  4. No arquivo .csproj, em cada configuração de plataforma

    eg

    adicione a seguinte linha:

    On

  5. Salve e feche o arquivo .csproj.

  6. No Gerenciador de Soluções, clique com o botão direito do mouse no projeto que você acabou de editar e clique em Recarregar Projeto.

Esse procedimento gera um assembly adicional chamado .xmlSerializers.dll na sua pasta de saída. Você precisará implantar esse assembly com sua solução.


Explicação

SGen por padrão apenas para tipos de proxy gera para “Qualquer CPU”. Isso acontece se você não definir as variables ​​correspondentes no seu arquivo de projeto.

SGenPlatformTarget é necessário para corresponder à sua PlatformTarget. Eu costumo pensar que isso é um bug no modelo do projeto. Por que a plataforma alvo do sgen deve diferir da do seu projeto? Se isso acontecer, você receberá uma exceção de tempo de execução

0x80131040: A definição do manifesto do assembly localizado não corresponde à referência do assembly

Você pode localizar a definição de tarefa msbuild analisando seu arquivo de projeto:

  

onde MSBuildToolsPath depende do seu http://msdn.microsoft.com/en-us/library/bb397428.aspx

Olhe dentro da definição de tarefa SGen para TargetFrameworkVersion 4.0 de

Caminho de instalação do Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Microsoft.CSharp.targets

para ver as variables ​​não documentadas como $ (SGenPlatformTarget) você está livre para definir no seu arquivo de projeto

      

No caso de alguém se deparar com esse problema de repente depois que tudo estava funcionando bem antes: Para mim, tinha a ver com a checkbox de seleção “Ativar apenas meu código (apenas gerenciado)” desmarcada no menu de opções (Opções -> Depuração) automaticamente desligado após instalar o .NET Reflector).

EDIT: O que é para dizer, claro, que essa exceção estava acontecendo antes, mas quando “ativar apenas meu código” está desativado, o assistente de debugging (se ativado), irá parar neste momento quando lançado.

Estou um pouco atrasado para a festa, mas achei a resposta anterior difícil de se trabalhar. Especificamente, o Visual Studio falharia sempre que eu tentava ver as propriedades do meu projeto. Eu acho que isso foi devido ao fato de que ele não entendia mais como ler o arquivo csproj. Dito isto…

Adicione o seguinte à sua linha de comando de evento pós-compilation:

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

Isso alavancará o sgen.exe diretamente para reconstruir o assembly Xml Serialization toda vez que você construir seu projeto para Debug ou Release.

Procure nas propriedades da solução. Na guia de criação, na parte inferior, há uma lista suspensa chamada “Gerar conjunto de serialização”

Uma solução ligeiramente diferente da fornecida pelo backup do cérebro poderia ser especificar diretamente o destino da plataforma exatamente onde você deve usá-lo da seguinte maneira:

   $(Platform)   $(PlatformTarget)