2011-04-03 3 views
4

Lors de l'élaboration d'un scénario de test pour comprendre la sérialisation, j'ai été confronté à un problème apparent, mais je n'arrive pas à le comprendre. Je veux être en mesure d'ajouter plusieurs objets à une liste <> puis sérialiser cette liste (dans ce cas j'utilise DataContractJsonSerializer). Après avoir créé les objets (node1 et node2), je veux les ajouter à une liste <> (cn) et le sérialiser. Cependant, j'obtiens une erreur d'argument invalide lors de l'ajout de node1 et node2 ("impossible de convertir" JSON_test.Aspirate "en" JSON_test.CompositeNode "). Je crois qu'il s'agit de faire connaître au tableau les types de base, mais je ne sais pas sais pas comment faire, ou si, en fait, c'est la question (encore très nouveau à tout cela).DataContract Sérialisation de List <> contenant des objets

Merci.

namespace JSON_test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Aspirate node1 = new Aspirate(25,40); 
      Dispense node2 = new Dispense(32,50); 
      ObjectToSerialize cn = new ObjectToSerialize(); 
      cn.CompositeNode.Add (node1); 
      cn.CompositeNode.Add (node2); 

      MemoryStream stream1 = new MemoryStream(); 
      DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ObjectToSerialize)); 
      ser.WriteObject(stream1, cn.CompositeNode); 
      stream1.Position = 0; 
      StreamReader sr = new StreamReader(stream1); 
      Console.WriteLine(sr.ReadToEnd()); 
      Console.ReadLine(); 
     } 
    } 

    [DataContract] 
    public class ObjectToSerialize 
    { 
     private List<CompositeNode> compNode; 
     [DataMember] 
     public List<CompositeNode> CompositeNode 
     { 
      get {return this.CompositeNode;} 
      set { this.compNode = value; } 
     } 

     public ObjectToSerialize() 
     { 
     } 
    } 

    [DataContract] 
    public class CompositeNode 
    { 

    } 

    [DataContract] 
    public class Aspirate 
    { 
     [DataMember] 
     public string NodeName = "Aspirate"; 
     [DataMember] 
     public double ZTravelHt; 
     [DataMember] 
     public double IndexHt; 

     public Aspirate(double ZTravelHt, double IndexHt) 
     { 
      this.ZTravelHt = ZTravelHt; 
      this.IndexHt = IndexHt; 
     } 
    } 

    [DataContract] 
    public class Dispense 
    { 
     [DataMember] 
     public string NodeName = "Dispense"; 
     [DataMember] 
     public double ZTravelHt; 
     [DataMember] 
     public double IndexHt; 

     public Dispense(double ZTravelHt, double IndexHt) 
     { 
      this.ZTravelHt = ZTravelHt; 
      this.IndexHt = IndexHt;    
     } 
    } 
} 

MISE à JOUR

namespace JSON_test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Aspirate node1 = new Aspirate(25,40); 
      Dispense node2 = new Dispense(32,50); 
      ObjectToSerialize cn = new ObjectToSerialize(); 
      cn.CompositeNode.Add (node1); 
      cn.CompositeNode.Add (node2); 

      MemoryStream stream1 = new MemoryStream(); 
      DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ObjectToSerialize), 
       new Type[] {typeof (Aspirate), typeof (Dispense)}); 
      ser.WriteObject(stream1, cn.CompositeNode); 
      stream1.Position = 0; 
      StreamReader sr = new StreamReader(stream1); 
      Console.WriteLine(sr.ReadToEnd()); 
      Console.ReadLine(); 
     } 
    } 

    [DataContract] 
    [KnownType(typeof(Aspirate))] 
    [KnownType(typeof(Dispense))] 
    public class ObjectToSerialize 
    { 
     private List<CompositeNode> compNode = new List<CompositeNode>(); 

     [DataMember] 
     public List<CompositeNode> CompositeNode 
     { 
      get {return this.compNode;} 
      set { this.compNode = value; } 
     } 

     public ObjectToSerialize() 
     { 

     } 
    } 

    [DataContract] 
    [KnownType(typeof(Aspirate))] 
    [KnownType(typeof(Dispense))] 
    public class CompositeNode 
    { 

    } 

    [DataContract] 
    public class Aspirate : CompositeNode 
    { 
     [DataMember] 
     public string NodeName = "Aspirate"; 
     [DataMember] 
     public double ZTravelHt; 
     [DataMember] 
     public double IndexHt; 

     public Aspirate(double ZTravelHt, double IndexHt) 
     { 
      this.ZTravelHt = ZTravelHt; 
      this.IndexHt = IndexHt; 
     } 
    } 

    [DataContract] 
    public class Dispense : CompositeNode 
    { 
     [DataMember] 
     public string NodeName = "Dispense"; 
     [DataMember] 
     public double ZTravelHt; 
     [DataMember] 
     public double IndexHt; 

     public Dispense(double ZTravelHt, double IndexHt) 
     { 
      this.ZTravelHt = ZTravelHt; 
      this.IndexHt = IndexHt;    
     } 
    } 
} 

Répondre

6

vous peut ajouter un KnownTypeAttribute au ObjectToSerialize pour laisser le sérialiseur savoir quels types d'attendre:

[DataContract] 
[KnownType(typeof(Aspirate))] 
[KnownType(typeof(Dispense))] 
public class ObjectToSerialize 
{ 
    .... 
} 

Je comprends que les classes Aspirate et Dispense sont dérivées de CompositeNode? Ce n'est pas clair à partir de votre exemple de code.

Vous avez une erreur dans votre code par la voie:

get {return this.CompositeNode;}  

devrait être:

get {return this.compNode;}  

Mise à jour: en resoponse à votre question dans les commentaires: vous avez à intialize la collection à l'intérieur d'un constructeur de ObjectToSerialize:

public ObjectToSerialize() 
{ 
    this.compNode = new List<CompositeNode>(); 
} 

Mise à jour 2: La ligne qui est faux est:

ser.WriteObject(stream1, cn.CompositeNode); 

Cela devrait être:

ser.WriteObject(stream1, cn); 

Par ailleurs, vous pouvez simplement écrire ceci:

DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ObjectToSerialize)); 

Vous avez déjà défini les types connus en utilisant des attributs. L'ajout des types connus au constructeur est redondant.

+0

Merci. Cela m'a déplacé dans la bonne direction. J'ai ajouté les KnownTypes, corrigé l'erreur et ajouté ': CompositeNode' aux classes Aspirate et Dispense. Il compile maintenant mais donne une exception NullReferenceException lorsque les nœuds sont ajoutés à la liste. Cela me dit que quelque chose est nécessaire dans la classe CompositeNode, mais mon inexpérience me gêne. Aucune suggestion? – user269689

+0

vous devez initialiser compNode dans classObjectToSerialize –

+0

Merci encore pour votre aide. J'ai changé "liste privée compNode" en "liste privée compNode = nouvelle liste ();". La liste est maintenant remplie avec les deux nœuds, mais je reçois une exception SerializationException - "ArrayOfCompositeNode: http: //schemas.datacontract.org/2004/07/JSON_test" n'est pas prévu " – user269689

Questions connexes