开发者

DataContract Serialization of List<> containing objects

While developing a test case to understand serialization, I've run into what looks like a straighforward problem but am unable to figure out. I want to be able to add multiple objects to a list<> and then serialize that list (in this case I'm using DataContractJsonSerializer). After creating the objects (node1 and node2), I want to add them to a List<> (cn) and serialize it. However, I get an invalid argument error when adding node1 and node2 ("cannot convert from 'JSON_test.Aspirate' to 'JSON_test.CompositeNode'). I believe it is a matter of letting the array know about the base types, but I don't know how to do that, or if in fact that is the issue (still very new to all this).

Thank you.

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

UPDATE

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


You can add a KnownTypeAttribute to the ObjectToSerialize to let the serializer know which types to expect:

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

I understand that the classes Aspirate and Dispense are derived from CompositeNode? This is not clear from your code example.

You have an error in your code by the way:

get {return this.CompositeNode;}    

should be:

get {return this.compNode;}    

Update: in resoponse to your question in the comments: you have to intialize the collection inside a constructor of ObjectToSerialize:

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

Update 2: The line that is wrong is:

ser.WriteObject(stream1, cn.CompositeNode);

This should be:

ser.WriteObject(stream1, cn);

By the way, you can just write this:

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

You already defined the known types by using attributes. Adding the known types to the constructor is redundant.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜