2009-10-24 4 views
3

This question peut être très similaire à mon, mais je ne peux pas voir la réponse dont j'ai besoin. J'ai une classe, appelée CASM, qui a un List<Action>. Je veux sérialiser cette classe (en utilisant le BinaryFormatter ou quelque chose de similaire). Cette classe et toutes les classes référencées dans les Action ont les attributs [Serializable] et [NonSerializable] corrects.Sérialiser une liste de délégués anonymes

Le problème vient quand sérialisation est tenté - il donne cette erreur:

Type 'CASM.CASM+<>c__DisplayClass2c' in Assembly 'CASM, Version=1.0.0.0, 
Culture=neutral, PublicKeyToken=null' is not marked as serializable. 

Ce <>c__DisplayClass2c est une classe interne autogenerated qui détient les différents types de délégué anonyme que je me sers dans ma demande. Cependant, comme on peut le voir sur l'image ci-dessous, il est [Serializable]:

alt text http://bayimg.com/image/maebbaacj.jpg

Quelle serait la meilleure façon de changer ma demande si cela ne fonctionne? Créer ma propre classe de type <>c__DisplayClass2c et la rendre sérialisable? Ou y a-t-il un meilleur moyen?


EDIT: En fin de compte je viens de faire ma propre classe, au lieu de celui généré automatiquement. Je contribue également au débogage, en ayant un nom descriptif plutôt que juste b__12().

+0

Vous dites que la classe est autogénérée - comment cela se fait-il? Le contrôle-t-il? Est-il généré par un composant tiers? –

+0

Il est généré automatiquement par le compilateur - il possède l'attribut [CompilerGenerated]. Je pense que c'est juste une classe/endroit pour stocker un certain nombre de délégués anonymes très semblables (ils sont tous vides et acceptent une chaîne [] comme paramètre dans ce cas). –

+0

Alors oui, essayez de générer votre propre classe. Vous pouvez également avoir un problème avec les méthodes anonymes (je ne l'ai pas essayé, donc je ne sais pas), auquel cas, essayez des versions non anonymes. Si cela ne fonctionne pas, vous pouvez d'abord transformer les méthodes en expressions (celles-ci devraient être sérialisables) –

Répondre

4

Il est généralement très peu logique de sérialiser un délégué. Normalement, vous choisissez de marquer les champs délégués comme [NonSerialized] et de les recréer en cas de besoin. Si votre intention principale est de stocker les délégués, alors je vous recommande de penser à une approche complètement différente, franchement.

De plus, notez que BinaryFormatter est fragile si vous prévoyez de conserver les données pendant toute la durée du temps (mais acceptable pour les données transitoires)

Pour regarder plus loin, je pense que nous aurions besoin d'examiner certains reproductibles code.


Mise à jour: En fait, je pense que vous pouvez sérialisation en écrivant vos propres classes de capture explicite (plutôt que ceux générés par le compilateur). Mais je pense toujours que le concept est fondamentalement défectueux. Et écrire des cours de capture à la main n'est pas amusant.


Pour adresser les points dans les commentaires; re le stockage à long terme - parce qu'il est so darned brittle - quelque chose d'aussi simple que de changer de:

public int Value {get;set;} 

à

private int value; 
public int Value { 
    get {return value;} 
    set { 
     if(value < 0) throw new ArgumentOutOfRangeException(); 
     this.value = value; 
    } 
} 

détruira sérialisation; comme changer les assemblages, taper les noms, "regarder ça marrant", etc.

Re les délégués; donner un exemple de capture manuelle; au lieu de:

int i = ... 
Predicate<Foo> test = delegate (Foo x) { return x.Bar == i;} 

vous pourriez faire:

int i = ... 
MyCapture cpt = new MyCapture(i); 
Predicate<Foo> test = cpt.MyMethod; 

avec

[Serializable] 
class MyCapture { 
    private int i; 
    public MyCapture(int i) {this.i = i;} 
    public bool MyMethod(Foo x) {return x.Bar == i;} 
} 

Comme vous pouvez le voir - pas toujours trivial (ce qui est le plus simple des exemples).

+0

Je savais qu'un commentaire comme celui-ci venait - il semble que ce soit une chose très étrange à faire. Cependant, les délégués semblent être la meilleure méthode (ou du moins la plus rapide) pour ce que j'essaie de faire. Créer les délégués prend un temps (relativement) long, donc ce serait bien si je pouvais les stocker. Je me suis rendu compte après avoir regardé Expression Tree du commentaire de Nader Shirazie que je suis en train d'essayer de recréer un système/syntaxe Expression Tree limité (ie construire du code à partir des délégués). Et pourquoi BinaryFormatter est-il mauvais pour le stockage à long terme des données? –

+0

Ah, merci. Donc un autre système comme protobuf-net ou XML n'aurait pas ce problème "fragile" car ils ne stockent pas les types/versions/assemblages etc. –

+0

Exactement; la plupart des sérialiseurs ne stockent que les * données *; Cela rend l'implémentation indépendante et généralement plus courte. 'BinaryFormatter' stocke les informations de type/champ, ce qui est ** très ** spécifique à l'implémentation. –

Questions connexes