Pergunta

Eu tenho que trabalhar um uma antiga aplicativo usado binaryFormatter para serializar os dados de aplicação para o filestream (dizer o nome do ficheiro de dados".oldformat") sem qualquer optimizazion a classe principal tem sido marcada com o atributo

<serializable()>public MainClass
....... 
end class

e o código de serialização

dim b as new binaryformatter
b.serialize(mystream,mymainclass)

Na tentativa de otimizar a serialização/desserialização processo eu simplesmente fizeram com que a classe implementa a interface ISerializable e escreveu alguns otimizado rotinas de serialização

<serializable()>public MainClass
       implements ISerializable
....... 
end class

A otimização funciona muito bem, mas eu PRECISO encontrar uma maneira de reatrive os dados dentro de arquivos antigos para compatibilidade com versões anteriores.

Como posso fazer isso??

Pierluigi

Foi útil?

Solução

STMAX tem uma excelente resposta, no entanto, eu o implementaria assim, que usa SerializationEntry.GetEnumerator() ao invés de try/catch. Dessa forma, é mais limpo e significativamente mais rápido.

public MainClass(SerializationInfo info, StreamingContext context) {
    int version = 0;
    foreach (SerializationEntry s in info)
    {
        if (s.Name == "version") 
        {
            version = (int)s.Value;
            break;
        }
    }

    switch (version) {
      case 0:
        // deserialize "old format"
        break;
      case 1:
        // deserialize "new format, version 1"
        break;
      default:
        throw new NotSupportedException("version " + version + " is not supported.");
    }
}

Eu preferiria uma versão LINQ usando .FirstordEfault (), mas a SerializationInfo não implementa Ienumerable - na face, estranhamente, ele nem implementa a antiga interface ienumerable.

Outras dicas

uma vez que você já implementou a interface ISerializable, você provavelmente também já adicionado o construtor exigido:

public MainClass(SerializationInfo info, StreamingContext context) {}

você pode usar a info-objeto passado para o construtor para recuperar dados a partir do arquivo serializado. por padrão (por exemplo,quando não ISerializable é implementada), os nomes de campos são utilizados como identificadores durante a serialização.então, se a sua classe antiga, tinha um campo de "int x" você pode anular esta usando:

this.x = info.GetInt32("x");

para as versões mais recentes normalmente eu adicionar uma "versão" de entrada durante a serialização, como este:

public void GetObjectData(SerializationInfo info, StreamingContext context) {
  info.AddValue("version", 1);
  info.AddValue("othervalues", ...);
}

durante a desserialização você pode verificar esta versão de entrada e anular a serialização de acordo:

public MainClass(SerializationInfo info, StreamingContext context) {
    int version;
    try {
       version = info.GetInt32("version");
    }
    catch {
       version = 0;
    }

    switch (version) {
      case 0:
        // deserialize "old format"
        break;
      case 1:
        // deserialize "new format, version 1"
        break;
      default:
        throw new NotSupportedException("version " + version + " is not supported.");
    }
}

eu não tiver compilado o código, podem conter erros de digitação.

espero que ajude.

Apenas tente a mesma coisa que você tem feito até agora

BinaryFormatter b = new BinaryFormatter();
MainClass a = b.DeSerialize(mystream) as MainClass;

Implementando iserializable não mudou sua classe original, basicamente você acabou de adicionar alguns métodos

Ao serializar seus objetos, adicione um campo de versão adicional (isso não deve adicionar muita sobrecarga). Em seguida, no seu método getObjectData, tente recuperar o campo de versão primeiro e com base se isso existe ou não (capturando a serializationException) desfiando a maneira antiga ou a nova maneira. A maneira antiga terá apenas todos os dados serializados para que você possa ligar para obter ... para todos os campos.

Seu código anterior deve funcionar. Você recebe uma exceção? Tente usar o novo construtor:

 Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top