XmlSerializer – Ocorreu um erro ao refletir o tipo

Usando o C # .NET 2.0, eu tenho uma class de dados compostos que tem o atributo [Serializable] nele. Eu estou criando uma class XMLSerializer e passando isso para o construtor:

 XmlSerializer serializer = new XmlSerializer(typeof(DataClass)); 

Eu estou recebendo uma exceção dizendo:

Houve um erro ao refletir o tipo.

Dentro da class de dados, há outro object composto. Isso também precisa ter o atributo [Serializable] , ou por tê-lo no object superior, aplica-o recursivamente a todos os objects dentro dele?

Olhe para a exceção interna que você está recebendo. Ele lhe dirá qual campo / propriedade está tendo problemas para serializar.

Você pode excluir campos / propriedades da serialização xml decorando-os com o atributo [XmlIgnore] .

Eu não acho que XmlSerializer usa o atributo [Serializable] , por isso duvido que é o problema.

Lembre-se de que as classs serializadas devem ter construtores padrão (isto é, sem parâmetros). Se você não tem nenhum construtor, tudo bem; mas se você tiver um construtor com um parâmetro, você precisará adicionar o parâmetro padrão também.

Eu tive um problema semelhante, e descobriu-se que o serializador não conseguia distinguir entre duas classs que eu tinha com o mesmo nome (uma era uma subclass da outra). A exceção interna ficou assim:

‘Tipos BaseNamespace.Class1’ e ‘BaseNamespace.SubNamespace.Class1’ usam o nome do tipo XML, ‘Class1’, do namespace ”. Use atributos XML para especificar um nome XML exclusivo e / ou namespace para o tipo.

Onde BaseNamespace.SubNamespace.Class1 é uma subclass de BaseNamespace.Class1.

O que eu precisava fazer era adicionar um atributo a uma das classs (adicionei à class base):

 [XmlType("BaseNamespace.Class1")] 

Nota: Se você tiver mais camadas de classs, também precisará adicionar um atributo a elas.

XmlSerializer também em atenção que o XmlSerializer não pode serializar propriedades abstratas. Veja a minha pergunta aqui (à qual adicionei o código da solução).

Serialização de XML e tipos herdados

Razões mais comuns por mim:

  - the object being serialized has no parameterless constructor - the object contains Dictionary - the object has some public Interface members 

Todos os objects no gráfico de serialização precisam ser serializáveis.

Como o XMLSerializer é um blackbox, verifique esses links se quiser depurar ainda mais o processo de serialização.

Alterando onde XmlSerializer saídas temporárias Assemblies

COMO: Depurar em um assembly gerado do .NET XmlSerializer

Se você precisar manipular atributos específicos (ou seja, Dicionário ou qualquer class), você pode implementar a interface IXmlSerialiable , que permitirá mais liberdade ao custo de codificação mais detalhada .

 public class NetService : IXmlSerializable { #region Data public string Identifier = String.Empty; public string Name = String.Empty; public IPAddress Address = IPAddress.None; public int Port = 7777; #endregion #region IXmlSerializable Implementation public XmlSchema GetSchema() { return (null); } public void ReadXml(XmlReader reader) { // Attributes Identifier = reader[XML_IDENTIFIER]; if (Int32.TryParse(reader[XML_NETWORK_PORT], out Port) == false) throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_PORT); if (IPAddress.TryParse(reader[XML_NETWORK_ADDR], out Address) == false) throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_ADDR); } public void WriteXml(XmlWriter writer) { // Attributes writer.WriteAttributeString(XML_IDENTIFIER, Identifier); writer.WriteAttributeString(XML_NETWORK_ADDR, Address.ToString()); writer.WriteAttributeString(XML_NETWORK_PORT, Port.ToString()); } private const string XML_IDENTIFIER = "Id"; private const string XML_NETWORK_ADDR = "Address"; private const string XML_NETWORK_PORT = "Port"; #endregion } 

Há um artigo interessante, que mostra uma maneira elegante de implementar uma maneira sofisticada de “estender” o XmlSerializer.


O artigo diz:

IXmlSerializable é coberto na documentação oficial, mas a documentação declara que não se destina a uso público e não fornece nenhuma informação além disso. Isso indica que a equipe de desenvolvimento queria reservar o direito de modificar, desativar ou mesmo remover completamente esse gancho de extensibilidade no futuro. No entanto, contanto que você esteja disposto a aceitar essa incerteza e lidar com possíveis mudanças no futuro, não há razão alguma em que você não possa tirar proveito dela.

Por isso, sugiro implementar suas próprias classs IXmlSerializable , para evitar implementações muito complicadas.

… pode ser simples implementar nossa class XmlSerializer personalizada usando a reflection.

Descobri que a class Dictionary no .Net 2.0 não é serializável usando XML, mas serializa bem quando a serialização binária é usada.

Eu encontrei um trabalho por aqui .

Eu recentemente tenho isso em uma class parcial de referência da web ao adicionar uma nova propriedade. A class gerada automaticamente estava adicionando os atributos a seguir.

  [System.Xml.Serialization.XmlElementAttribute(Order = XX)] 

Eu precisava adicionar um atributo semelhante a um pedido maior que o anterior na sequência gerada automaticamente e isso corrigiu isso para mim.

Eu também pensei que o atributo Serializable tinha que estar no object, mas a menos que eu esteja sendo um noob completo (eu estou no meio de uma session de codificação tarde da noite) os seguintes trabalhos do SnippetCompiler :

 using System; using System.IO; using System.Xml; using System.Collections.Generic; using System.Xml.Serialization; public class Inner { private string _AnotherStringProperty; public string AnotherStringProperty { get { return _AnotherStringProperty; } set { _AnotherStringProperty = value; } } } public class DataClass { private string _StringProperty; public string StringProperty { get { return _StringProperty; } set{ _StringProperty = value; } } private Inner _InnerObject; public Inner InnerObject { get { return _InnerObject; } set { _InnerObject = value; } } } public class MyClass { public static void Main() { try { XmlSerializer serializer = new XmlSerializer(typeof(DataClass)); TextWriter writer = new StreamWriter(@"c:\tmp\dataClass.xml"); DataClass clazz = new DataClass(); Inner inner = new Inner(); inner.AnotherStringProperty = "Foo2"; clazz.InnerObject = inner; clazz.StringProperty = "foo"; serializer.Serialize(writer, clazz); } finally { Console.Write("Press any key to continue..."); Console.ReadKey(); } } } 

Eu imagino que o XmlSerializer está usando reflection sobre as propriedades públicas.

Eu tive uma situação em que a Ordem era a mesma para dois elementos seguidos

 [System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")] 

…. algum código …

 [System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")] 

Quando mudei o código para incrementar a ordem em um para cada nova propriedade na class, o erro desapareceu.

Acabei de receber o mesmo erro e descobri que uma propriedade do tipo IEnumerable era o problema. Parece que IEnumerable não pode ser serializado diretamente.

Observe também que não é possível serializar os controles da interface do usuário e que qualquer object que você queira passar para a área de transferência deve ser serializável, caso contrário, não poderá ser passado para outros processos.

Eu tenho usado a class NetDataSerialiser para serializar minhas classs de domínio. Classe NetDataContractSerializer .

As classs de domínio são compartilhadas entre cliente e servidor.

[System.Xml.Serialization.XmlElementAttribute (“strFieldName”, Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

//Ou

[XmlIgnore] string [] strFielsName {get; conjunto;}

Eu tive o mesmo problema e no meu caso, o object tinha um ReadOnlyCollection. Uma coleção deve implementar o método Add para ser serializável.