Pourquoi ne peut pas l'attribut « NonSerialized » être utilisé au niveau de la classe? Comment prévenir la sérialisation d'une classe?

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

Question

J'ai un objet de données qui est profondément cloné en utilisant une sérialisation binaire. Cet objet de données prend en charge les propriétés événements ont changé, par exemple, PriceChanged.

Disons que je joint un gestionnaire à PriceChanged. Lorsque le code tente de sérialiser PriceChanged, il déclenche une exception que le gestionnaire n'a pas été marqué comme sérialisable.

Mes options:

  • Je ne peux pas retirer facilement tous les gestionnaires de l'événement avant la sérialisation
  • Je ne veux pas marquer le gestionnaire comme sérialisable parce que je dois marquer récursive toutes les dépendances handlers ainsi.
  • Je ne veux pas marquer comme PriceChanged NonSerialized - il y a des dizaines d'événements comme celui-ci qui pourraient avoir des gestionnaires. EDIT: Une autre raison pour laquelle je ne peux pas le faire est parce que les classes de données (et donc les événements) sont générés et je n'ai pas un contrôle direct sur le code de génération. Idéalement, le code de génération marquerait simplement tous les événements comme NonSerialized.
  • Idéalement, je voudrais .NET arrêter juste aller sur le graphe d'objet à ce moment-là et en faire une « feuille ». Alors pourquoi ne pas laisser .NET à marquer comme NonSerialized une classe entière?

-

J'ai finalement travaillé autour de ce problème en rendant le gestionnaire et la mise en œuvre ISerializable ne rien faire dans la méthode constructeur de sérialisation / GetDataObject. Mais, le gestionnaire est toujours sérialisé, juste avec toutes ses dépendances réglé sur null - donc je devais expliquer cela aussi.

Y at-il une meilleure façon d'éviter la sérialisation d'une classe entière? C'est, qui ne nécessite pas de comptabilité pour les dépendances nulles?

Était-ce utile?

La solution

Alors que je suis pas d'accord avec l'approche (je voudrais simplement marquer les événements comme NonSerialized, peu importe combien il y a), vous pouvez probablement le faire en utilisant les mères porteuses de sérialisation.

L'idée est que vous créez un objet qui implémente ISerializationSurrogate et fait essentiellement ce que vous faites déjà - rien dans les méthodes GetObjectData et SetObjectData. La différence est que vous customisera la sérialisation du délégué, et non la classe contenant.

Quelque chose comme:

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;
    }
}

Ensuite, vous enregistrez ceci avec le formatter en utilisant les procédures décrites dans cette colonne MSDN . Ensuite, chaque fois que le formatter rencontre un délégué, il utilise la mère porteuse au lieu de serializating le délégué directement.

Autres conseils

  

... il y a des dizaines d'événements ...

Personnellement, je voudrais juste ajouter les marqueurs non sérialisés, qui pour des événements comme le terrain est plus facile à faire par:

[field: NonSerialized]
public event SomeEventType SomeEventName;

(vous n'avez pas besoin d'ajouter un délégué de support manuel)

Quelles sont vos exigences de sérialisation exactement? BinaryFormatter est à bien des égards le moins respectueux des serializers; les conséquences sur les événements sont un peu laid, et il est très fragile si stocké (OMI il est seulement vraiment adapté pour le transport, et non pour le stockage).

Cependant; il y a beaucoup de bonnes alternatives qui soutiendrait les plus communs scénarios « clone profond »:

  • XmlSerializer (mais limité aux membres du public)
  • DataContractSerializer / NetDataContractSerializer
  • protobuf-net (qui comprend Serializer.DeepClone à cet effet)

(notez que dans la plupart des personnes le soutien de sérialisation nécessiterait des attributs supplémentaires, donc pas très différent d'ajouter le [NonSerialized] attribue en premier lieu!)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top