Pergunta

Meu repositório tem List<Student>, List<Course> e List<Enrolment> onde uma inscrição tem Enrolment.Student e Enrolment.Course que são referências a um dos alunos ou cursos nas duas listas anteriores.

Quando eu uso XmlSerializer no meu repositório ele gera dados redundantes como ele serializa todas as propriedades de cada aluno em List<Student> em seguida, novamente para cada referência a esses mesmos estudantes em List<Enrolment>. Eu estou procurando uma maneira elegante de resolver esta situação.

Depois de desserialização posso corrigir as referências usando os valores de ID nas instâncias de objetos duplicados criados pela desserialização mas isso parece hackish.

Um método para corrigir a saída redundante é XmlIgnore Enrolment.Student e Enrolment.Course e criar mais duas propriedades de serialização - Enrolment.StudentID e Enrolment.CourseID. No entanto, durante a desserialização, as referências para Enrolment.Student e Enrolment.Course não pode ser definido (AFAIK) já que os resultados de desserialização de List<Student> e List<Course> não estão disponíveis.

Outro método que eu pensava é serializar mais abaixo na minha hierarquia de objetos fazendo cada uma das minhas listas separadamente e controlar a ordem de desserialização -. Eu prefiro não fazer isso

Outro método seria XmlIgnore List<Enrolment> e criar uma classe auxiliar serialização de inscrição que inicializa List<Enrolment> após a desserialização de si é completa. Este parece ser um monte de esforço.

Como outras pessoas serializar / desserializar várias referências ao mesmo objeto usando XmlSerializer?

Foi útil?

Solução

Oh as dores de serialização: -> ...

Nunca houve uma solução genérica para isso, eu acho que é por isso que MS despojado-lo para fora do quadro Silverlight.

Eu nunca confiar em quaisquer mecanismos de serialização automáticas do .NET Framework. Para os meus próprios modelos e repositórios, eu geralmente sabem ou podem facilmente determinar programaticamente quais propriedades são simples escalares (números / cordas / etc) e que são links para outros objetos (assim como quais são listas de qualquer um).

Existem basicamente 2 cenários:

1: Queremos serialize / transferência apenas as informações plana de objetos. Nesse caso, eu transferir apenas as respectivas identificações para propriedades que possuem links para outros objetos. O receptor pode então fazer consultas subsequentes para obter todos os outros objetos que precisam.

2: Queremos transferir tanta informação quanto possível, ou seja, XML mais profundo aninhada com vários níveis, principalmente para alguns tudo funcionalidade de relatórios exibindo diretamente usando apenas alguns CSS no XML. Nesse caso, é realmente desejado que os objetos que são o mesmo será resolvido várias vezes na árvore XML.

Às vezes eu preciso ajustar o primeiro cenário um pouco a fim de evitar muitas chamadas de consulta subseqüentes, mas geralmente eu nos damos muito bem. Ou seja, Eu construí na nossa base de código que podemos especificar quais objetos adicional queremos resolver quando, e / ou é configurado em algum lugar.

Outras dicas

Não há uma solução para este problema usando o Serializer XML. Ele não tem um conceito de identidade que ele pode usar para remover a duplicação.

O melhor que você pode fazer é serializar o conjunto de objetos separadamente de suas referências. Você poderia, então, recriar suas listas após a desserialização.

BTW, você está ciente de que o XmlSerializer não é específico para C #?

Você pode implementar a interface IXmlSerializable para inscrição e no método WriteXml gerar XML estudante e curso que irá contém apenas as chaves v.g.:.

<Student Id="5"/>
<Course Id="6"/>

e no método ReadXml você pode carregar referências deste. Você também deve definir atributo XmlIgnore para Student e Curso propriedade.

Como é que este som como uma solução:

  1. XmlIgnore cada secundário isto é, referência Enrolment.Student & Enrolment.Course
  2. criar uma propriedade para cada secundário de referência que é usado para serialize / desserializar uma chave estrangeira para que a referência em vez - Prefixo com XML_FK. por exemplo XML_FK_Student & XML_FK_Course
  3. Criar um XML_FinalizeDeserialization método que é chamado após a desserialização de carga as referências usando os estrangeira principais propriedades.

Você deve / pode usar o acompanhamento de Referência com o serializador DataContract:

//deserilaize:
using(MemoryStream memStmBack = new MemoryStream()) {
  var serializerForth = new DataContractSerializer(
    typeof(YourType),
    null,
    0x7FFF /*maxItemsInObjectGraph*/ ,
    false /*ignoreExtensionDataObject*/ ,
    true /*preserveObjectReferences*/ ,
    null /*dataContractSurrogate*/ );

  byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
  memStmBack.Write(data, 0, data.Length);
  memStmBack.Position = 0;
  var lsBack = (YourType) serializerForth.ReadObject(memStmBack);

}
//serialize...
using(MemoryStream memStm = new MemoryStream()) {
    var serializer = new DataContractSerializer(
      typeof(YourType),
      knownTypes,
      0x7FFF /*maxItemsInObjectGraph*/ ,
      false /*ignoreExtensionDataObject*/ ,
      true /*preserveObjectReferences*/ ,
      null /*dataContractSurrogate*/ );

    serializer.WriteObject(memStm, yourType);

    memStm.Seek(0, SeekOrigin.Begin);

    using(var streamReader = new StreamReader(memStm)) {
        result = streamReader.ReadToEnd();

Ou uso

[Serializable]
[DataContract(IsReference = true)]
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top