Por que o atributo 'não serializado' não pode ser usado no nível da aula? Como impedir a serialização de uma classe?

StackOverflow https://stackoverflow.com/questions/2467376

Pergunta

Eu tenho um objeto de dados que é clonado profundamente usando uma serialização binária. Esse objeto de dados suporta eventos alterados da propriedade, por exemplo, PriceChanged.

Digamos que eu anexei um manipulador à PriceChanged. Quando o código tenta serializar em serializar o PriceChanged, ele gera uma exceção de que o manipulador não é marcado como serializável.

Minhas alternativas:

  • Não posso remover facilmente todos os manipuladores do evento antes da serialização
  • Não quero marcar o manipulador como serializável, porque teria que marcar recursivamente todas as dependências dos manipuladores também.
  • Eu não quero marcar o PriceChanged como não serralizado - há dezenas de eventos como esse que podem ter manipuladores. EDIT: Outra razão pela qual não posso fazer isso é porque as classes de dados (e, portanto, os eventos) são gerados e não tenho controle direto sobre o código de geração. Idealmente, o código de geração apenas marcaria todos os eventos como não serralizados.
  • Idealmente, eu gostaria .NET para parar de descer o gráfico de objetos naquele momento e fazer disso uma 'folha'. Então, por que o .NET não permite que uma classe inteira seja marcada como não serrializada?

--

Finalmente trabalhei nesse problema, tornando o manipulador implementar iserializável e não fazendo nada no método Serialize Constructor/ GetDataObject. Mas, o manipulador ainda está serializado, apenas com todas as suas dependências definidas como NULL - então eu também tive que explicar isso.

Existe uma maneira melhor de impedir a serialização de uma classe inteira? Ou seja, aquele que não requer contabilidade para as dependências nulas?

Foi útil?

Solução

Enquanto eu tendem a discordar da abordagem (eu simplesmente marcaria os eventos como não serralizados, independentemente de quantos existam) você provavelmente poderia fazer isso usando substitutos de serialização.

A idéia é que você crie um objeto que implemente o iserializaçõesurrogate e basicamente faça o que você já está fazendo - nada nos métodos GetObjectData e setObjectData. A diferença é que você estaria personalizando a serialização do delegado, não a classe que o contém.

Algo como:

class DelegateSerializationSurrogate : ISerializationSurrogate {
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) {
        // do nothing
    }
    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context) {
        // do nothing
        return null;
    }
}

Em seguida, você registra isso no formatador usando os procedimentos descrito nesta coluna MSDN. Então, sempre que o formatador encontrar um delegado, ele usa o substituto em vez de serializar diretamente o delegado.

Outras dicas

... Existem dezenas de eventos ...

Pessoalmente, então eu acrescentaria os marcadores não serrializados, que para eventos semelhantes a campo são mais facilmente feitos via:

[field: NonSerialized]
public event SomeEventType SomeEventName;

(você não precisa adicionar um delegado de apoio manual)

Quais são os seus requisitos de serialização exatamente? BinaryFormatter é de muitas maneiras o menos amigável dos serializadores; As implicações nos eventos são um pouco feias e são muito quebradiças se armazenadas (IMO é realmente adequada para transporte, não para armazenamento).

No entanto; Existem muitas alternativas boas que apoiariam cenários mais comuns de "clone profundo":

  • XmlSerializer (mas limitado a membros públicos)
  • DataContractSerializer / NetDataContractSerializer
  • Protobuf-net (que inclui Serializer.DeepClone para esse fim)

(Observe que na maioria desses suporte de serialização exigiria atributos extras; portanto, não muito diferente de adicionar o [NonSerialized] atributos em primeiro lugar!)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top