Um aplicativo com o qual estou trabalhando está falhando quando tento serializar tipos.
Uma declaração como
XmlSerializer lizer = new XmlSerializer(typeof(MyType));
produz:
System.IO.FileNotFoundException occurred
Message="Could not load file or assembly '[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
Source="mscorlib"
FileName="[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
FusionLog=""
StackTrace:
at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
Não defino nenhum serializador especial para minha classe.
Como posso resolver este problema?
c#
xml-serialization
Irwin
fonte
fonte
Generate serialization assembly
menu suspenso para "Ativado", em vez de "Automático".Respostas:
Acredite ou não, este é um comportamento normal. Uma exceção é lançada, mas tratada pelo XmlSerializer, portanto, se você a ignorar, tudo deve continuar bem.
Achei isso muito irritante e houve muitas queixas sobre isso, se você pesquisar um pouco, mas pelo que li, a Microsoft não planeja fazer nada a respeito.
Você pode evitar a obtenção de pop-ups de exceção o tempo todo durante a depuração se desativar as exceções de primeira chance para essa exceção específica. No Visual Studio, vá para Debug -> Exceptions (ou pressione Ctrl+ Alt+ E), Common Language Runtime Exceptions -> System.IO -> System.IO.FileNotFoundException .
Você pode encontrar informações sobre outra maneira de contornar isso na postagem do blog C # XmlSerializer FileNotFound (que discute a ferramenta XmlSerializerPreCompiler da ferramenta de Chris Sells ).
fonte
Como Martin Sherburn disse, esse é um comportamento normal. O construtor do XmlSerializer primeiro tenta localizar um assembly chamado [YourAssembly] .XmlSerializers.dll que deve conter a classe gerada para serialização do seu tipo. Como essa DLL ainda não foi gerada (não é por padrão), é lançada uma FileNotFoundException. Quando isso acontece, o construtor do XmlSerializer captura essa exceção e a DLL é gerada automaticamente em tempo de execução pelo construtor do XmlSerializer (isso é feito gerando arquivos de origem C # no diretório% temp% do seu computador e compilando-os usando o compilador C #). Construções adicionais de um XmlSerializer para o mesmo tipo usarão apenas a DLL já gerada.
A exceção é tratada pelo construtor do XmlSerializer. Não é necessário fazer nada, basta clicar em 'Continuar' (F5) para continuar executando o programa e tudo ficará bem. Se você está incomodado com as exceções que interrompem a execução do programa e exibem um auxiliar de exceção, você tem o 'Just My Code' desativado ou o FileNotFoundException definido para interromper a execução quando lançada, em vez de quando 'User- sem tratamento ".
Para ativar 'Just My Code', vá para Ferramentas >> Opções >> Depuração >> Geral >> Ativar Just My Code. Para desativar a interrupção da execução quando o FileNotFound for acionado, vá para Debug >> Exceptions >> Find >>, digite 'FileNotFoundException' >> desmarque a caixa de seleção 'Thrown' em System.IO.FileNotFoundException.
fonte
FileNotFoundException
será lançado. A diferença não está em como a existência da montagem é verificada, mas em como gerá-la quando é determinado que está faltando. Antes, usava a geração de código C # textual com uma chamada para o compilador C # para criar a IL. A partir do .NET 4.5, emite IL diretamente, sem o uso de um compilador.File.Exists()
pode não ser suficiente. A localização de um assembly não é uma tarefa simples, o tempo de execução é exibido em vários locais e acredito que o comportamento muda de acordo com o ambiente (aplicativo do console x hospedado no IIS, etc.). Eu acho que o que deveria ter sido implementado foi umTryLoadAssembly()
ou algo semelhante.Nas propriedades do projeto do Visual Studio (página "Build", se bem me lembro), existe uma opção dizendo "gerar assembly de serialização". Tente ativá-lo para um projeto que gera [Contendo Assembly do MyType] .
fonte
Existe uma solução alternativa para isso. Se você usar
deve evitar essa exceção. Isso funcionou para mim.
AVISO: Não use várias vezes, ou você terá um vazamento de memória
Você perderá memória como um louco se usar esse método para criar instâncias do
XmlSerializer
mesmo tipo mais de uma vez!Isso ocorre porque esse método ignora o cache interno fornecido aos construtores
XmlSerializer(type)
eXmlSerializer(type, defaultNameSpace)
(todos os outros construtores também ignoram o cache).Se você usar qualquer método para criar um XmlSerializer que não seja desses dois construtores, implemente seu próprio cache ou sofrerá hemorragia na memória.
fonte
XmlSerializer
mesmo tipo mais de uma vez! Isso ocorre porque esse método ignora o cache interno fornecido aos construtoresXmlSerializer(type)
eXmlSerializer(type, defaultNameSpace)
(todos os outros construtores também ignoram o cache). Se você usar qualquer método para criar um métodoXmlSerializer
que não seja através desses dois construtores, deverá implementar seu próprio cache ou sofrerá hemorragia na memória.FromTypes
parece preencher o cache. Portanto, deve ser uma maneira válida de aquecer umXmlSerializer
cache vazio em uma instrução (como o artigo sugere), mas uma maneira realmente ruim de recuperar qualquer coisa a partir dele (deve ser feita apenas pelos construtores mais simples). De qualquer forma, eu não sabia que era um bug, sempre pensei que qualquer coisa que vazasse deveria vazar (como osXmlSerializer
construtores mais avançados ). Eu nem consideraria usar,FromTypes()
já que você pode fazertypes.Select(t => new XmlSerializer(t))
.FromTypes
tem seu apelo - mesmo que as exceções lançadas sejam todas capturadas, é uma operação inestimável; a abordagem 'cache à sua maneira' parece ser a única solução alternativa, pois a única correção oficialmente suportada parece estar em um assembly obscuro baseado na Web. (edit: francamente, eu sou todo para portar tudo para contratos de dados :))Corri para esse problema exato e não consegui contornar isso com nenhuma das soluções mencionadas.
Então eu finalmente encontrei uma solução. Parece que o serializador precisa não apenas do tipo, mas também dos tipos aninhados. Alterando isso:
Para isso:
Corrigido o problema para mim. Sem mais exceções ou qualquer coisa.
fonte
var xmlSerializer = new XmlSerializer(typeof(T), typeof(T).GetNestedTypes());
Minha solução é ir direto à reflexão para criar o serializador. Isso ignora o carregamento estranho de arquivo que causa a exceção. Empacotei isso em uma função auxiliar que também cuida do armazenamento em cache do serializador.
fonte
Para evitar a exceção, você precisa fazer duas coisas:
Adicione o atributo System.Xml.Serialization.XmlSerializerAssembly à sua classe. Substitua 'MyAssembly' pelo nome do assembly em que MyClass está.
Gere o arquivo de serialização usando o utilitário sgen.exe e implante-o com o assembly da classe.
'sgen.exe MyAssembly.dll' gerará o arquivo MyAssembly.XmlSerializers.dll
Essas duas alterações farão com que o .net encontre diretamente o assembly. Eu verifiquei e funciona no .NET framework 3.5 com Visual Studio 2008
fonte
Essa exceção também pode ser interceptada por um assistente de depuração gerenciada (MDA) chamado BindingFailure.
Esse MDA é útil se seu aplicativo for projetado para ser fornecido com conjuntos de serialização pré-compilados. Fazemos isso para aumentar o desempenho de nosso aplicativo. Isso nos permite garantir que os conjuntos de serialização pré-criados estejam sendo construídos adequadamente pelo nosso processo de criação e carregados pelo aplicativo sem serem recriados em tempo real.
Realmente não é útil, exceto neste cenário, porque, como outros pôsteres disseram, quando um erro de ligação é capturado pelo construtor Serializer, o conjunto de serialização é recriado em tempo de execução. Então você geralmente pode desligá-lo.
fonte
A função XmlSerializer.FromTypes não lança a exceção, mas vaza a memória. É por isso que você precisa armazenar em cache esse serializador para todos os tipos, para evitar vazamento de memória em todas as instâncias criadas.
Crie sua própria fábrica XmlSerializer e use-a simplesmente:
A fábrica se parece com:
Versão mais complicada sem possibilidade de vazamento de memória (por favor, alguém reveja o código):
fonte
A solução de problemas de erros de compilação, por outro lado, é muito complicada. Esses problemas se manifestam em um FileNotFoundException com a mensagem:
Você pode se perguntar o que um arquivo não encontrado tem a ver com instanciar um objeto serializador, mas lembre-se: o construtor grava arquivos C # e tenta compilá-los. A pilha de chamadas dessa exceção fornece algumas informações boas para apoiar essa suspeita. A exceção ocorreu enquanto o XmlSerializer tentou carregar um assembly gerado pelo CodeDOM chamando o método System.Reflection.Assembly.Load. A exceção não fornece uma explicação sobre o motivo pelo qual o assembly que o XmlSerializer deveria criar não estava presente. Em geral, o assembly não está presente porque a compilação falhou, o que pode acontecer porque, em raras circunstâncias, os atributos de serialização produzem código que o compilador C # falha ao compilar.
Nota Este erro também ocorre quando o XmlSerializer é executado em uma conta ou em um ambiente de segurança que não pode acessar o diretório temporário.
Fonte : http://msdn.microsoft.com/en-us/library/aa302290.aspx
fonte
Nas propriedades do projeto do Visual Studio, há uma opção dizendo "gerar assembly de serialização". Tente ativá-lo para um projeto que gera [Contendo Assembly do MyType].
fonte
Uma classe personalizada para serializar:
Anexei o trecho de código. Talvez isso possa ajudá-lo.
fonte
Eu estava tendo um problema semelhante e ignorar a exceção não funcionou para mim. Meu código estava chamando a configuração do NServiceBus '
Configure.With(...).XmlSerializer()...
O que o corrigiu para mim foi mudar a plataforma do meu projeto.
fonte
Apenas como referência. Retirando da resposta e dos comentários do DB, eu vim com esta solução que é próxima da solução do DB. Funciona bem em todos os meus casos e é seguro para threads. Eu não acho que o uso de um ConcurrentDictionary tivesse sido bom.
Uso:
fonte
Seu tipo pode fazer referência a outros assemblies que não podem ser encontrados nem no GAC nem na pasta bin local ==> ...
Você pode dar um exemplo do tipo que deseja serializar?
Nota: Verifique se o seu tipo implementa Serializable.
fonte
Eu estava recebendo o mesmo erro e era devido ao tipo que estava tentando desserializar por não ter um construtor sem parâmetros padrão . Eu adicionei um construtor e ele começou a funcionar.
fonte
Eu tive o mesmo problema até usar uma ferramenta de terceiros para gerar a classe a partir do XSD e funcionou! Eu descobri que a ferramenta estava adicionando algum código extra na parte superior da minha classe. Quando adicionei esse mesmo código ao topo da minha classe original, ele funcionou. Aqui está o que eu adicionei ...
fonte
Visto muitas recomendações para usar um
ConcurrentDictionary
, mas não há exemplos sólidos, então vou jogar meu chapéu nessa corrida de soluções. Como não sou desenvolvedor de thread-safe, se esse código não for sólido, fale por aqueles que seguem a seguir.Vi outras postagens envolvendo
ConcurrentDictionary
eLazy
carregando o valor. Não tenho certeza se isso é relevante aqui ou não, mas aqui está o código para isso:fonte