Encontrei algumas dicas ao fazer serialização XML em C # que pensei em compartilhar:
- Você não pode serializar itens que são somente leitura (como KeyValuePairs)
- Você não pode serializar um dicionário genérico. Em vez disso, tente esta classe de wrapper (em http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx ):
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
}
Alguma outra dica de serialização XML por aí?
c#
xml-serialization
kurious
fonte
fonte
Respostas:
Outra grande dificuldade: ao produzir XML através de uma página da Web (ASP.NET), você não deseja incluir a Marca de Pedido de Byte Unicode . Obviamente, as maneiras de usar ou não a BOM são quase as mesmas:
RUIM (inclui lista técnica):
BOA:
Você pode explicitamente passar false para indicar que não deseja a BOM. Observe a clara e óbvia diferença entre
Encoding.UTF8
eUTF8Encoding
.Os três bytes extras de BOM no início são (0xEFBBBF) ou (239 187 191).
Referência: http://chrislaco.com/blog/trou Troubleshooting - common - problems - with - the - xmlserializer/
fonte
XmlTextWriter
no .NET 2.0 ou superior.Ainda não posso fazer comentários, então comentarei o post do Dr8k e farei outra observação. Variáveis privadas que são expostas como propriedades públicas de getter / setter e são serializadas / desserializadas como tais por meio dessas propriedades. Fizemos isso no meu antigo emprego o tempo todo.
Porém, uma coisa a ser observada é que, se você tiver alguma lógica nessas propriedades, a lógica será executada; portanto, às vezes, a ordem da serialização é realmente importante. Os membros são implicitamente ordenados pela maneira como são ordenados no código, mas não há garantias, especialmente quando você está herdando outro objeto. Ordená-los explicitamente é uma dor na parte traseira.
Eu fui queimado por isso no passado.
fonte
Ao serializar em uma sequência XML a partir de um fluxo de memória, use MemoryStream # ToArray () em vez de MemoryStream # GetBuffer () ou você terminará com caracteres indesejados que não serão desserializados adequadamente (devido ao buffer extra alocado).
http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer(VS.80).aspx
fonte
Se o serializador encontrar um membro / propriedade que tenha uma interface como seu tipo, ele não será serializado. Por exemplo, o seguinte não será serializado para XML:
Embora isso seja serializado:
fonte
IEnumerables<T>
que são gerados por meio de retornos de rendimento não são serializáveis. Isso ocorre porque o compilador gera uma classe separada para implementar retorno de rendimento e essa classe não é marcada como serializável.fonte
Você não pode serializar propriedades somente leitura. Você deve ter um getter e um setter, mesmo que nunca pretenda usar a desserialização para transformar XML em um objeto.
Pelo mesmo motivo, você não pode serializar propriedades que retornam interfaces: o desserializador não saberia qual classe concreta instanciar.
fonte
Ah, eis uma boa: como o código de serialização XML é gerado e colocado em uma DLL separada, você não recebe nenhum erro significativo quando há um erro no código que interrompe o serializador. Apenas algo como "incapaz de localizar s3d3fsdf.dll". Agradável.
fonte
Não é possível serializar um objeto que não possui um construtor sem parâmetros (apenas foi mordido por esse).
E, por algum motivo, nas seguintes propriedades, o Value é serializado, mas não o FullName:
Nunca resolvi o porquê, apenas mudei Valor para interno ...
fonte
double?
mas apenasdouble
?null
e não, portanto, gerar qualquer XML quando serializadoMais uma observação: você não pode serializar membros da classe privada / protegida se estiver usando a serialização XML "padrão".
Mas você pode especificar uma lógica de serialização XML personalizada implementando IXmlSerializable em sua classe e serializar todos os campos particulares que você precisa / deseja.
http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx
fonte
Se o assembly gerado por serialização XML não estiver no mesmo contexto de carregamento que o código que está tentando usá-lo, você encontrará erros impressionantes, como:
A causa disso para mim foi um plugin carregado usando o contexto LoadFrom, que tem muitas desvantagens em usar o contexto Load. Um pouco divertido rastrear esse abaixo.
fonte
Você pode enfrentar problemas para serializar objetos do tipo Cor e / ou Fonte.
Aqui estão os conselhos que me ajudaram:
http://www.codeproject.com/KB/XML/xmlsettings.aspx
http://www.codeproject.com/KB/cs/GenericXmlSerializition.aspx
fonte
Consulte " Suporte à Vinculação de Atributos da Linguagem de Definição de Esquema XML Avançado " para obter detalhes sobre o que é suportado pelo XML Serializer e para obter detalhes sobre a maneira como os recursos XSD suportados são suportados.
fonte
Se você tentar serializar uma matriz
List<T>
ouIEnumerable<T>
que contenha instâncias de subclasses deT
, precisará usar o XmlArrayItemAttribute para listar todos os subtipos que estão sendo usados. Caso contrário, você receberá uma mensagem inútilSystem.InvalidOperationException
em tempo de execução ao serializar.Aqui está parte de um exemplo completo da documentação
fonte
Variáveis / propriedades privadas não são serializadas no mecanismo padrão para serialização XML, mas estão na serialização binária.
fonte
As propriedades marcadas com o
Obsolete
atributo não são serializadas. Eu não testei comDeprecated
atributo, mas presumo que funcionaria da mesma maneira.fonte
Eu realmente não posso explicar este, mas achei que isso não seria serializado:
mas isso irá:
E também é importante notar que, se você estiver serializando para um fluxo de memórias, convém procurar 0 antes de usá-lo.
fonte
Tenha cuidado com os tipos de serialização sem serialização explícita, pois isso pode resultar em atrasos, enquanto o .Net os cria. Descobri isso recentemente ao serializar RSAParameters .
fonte
Se o seu XSD faz uso de grupos de substituição, é provável que você não possa (des) serializá-lo automaticamente. Você precisará escrever seus próprios serializadores para lidar com esse cenário.
Por exemplo.
Neste exemplo, um envelope pode conter mensagens. No entanto, o serializador padrão do .NET não distingue entre Message, ExampleMessageA e ExampleMessageB. Serializará somente para e da classe Message base.
fonte
Acredito que isso também o faça se você estiver expondo os membros privados por meio de propriedades públicas - os membros privados não são serializados, portanto todos os membros públicos estão referenciando valores nulos.
fonte