DataContract List<>的序列化包含对象

时间:2011-04-03 20:54:53

标签: c# serialization

在开发一个用于理解序列化的测试用例的同时,我遇到了一个看起来像是一个直截了当的问题,但我无法弄明白。我希望能够将多个对象添加到列表<>然后序列化该列表(在这种情况下,我正在使用DataContractJsonSerializer)。创建对象(node1和node2)后,我想将它们添加到List<> (cn)并序列化它。但是,在添加node1和node2时,我得到一个无效的参数错误(“无法从'JSON_test.Aspirate'转换为'JSON_test.CompositeNode')。我相信这是让阵列知道基类型的问题,但我不知道我不知道该怎么做,或者事实上这是问题(对所有这些来说还是很新的)。

谢谢。

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

更新

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

1 个答案:

答案 0 :(得分:7)

您可以向KnownTypeAttribute添加ObjectToSerialize,让序列化程序知道预期的类型:

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

我了解课程AspirateDispense来自CompositeNode?您的代码示例中不清楚这一点。

顺便说一下,您的代码中有错误:

get {return this.CompositeNode;}    

应该是:

get {return this.compNode;}    

更新:在评论中对你的问题进行了再次访问:你必须在ObjectToSerialize的构造函数中初始化集合:

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

更新2:错误的行是:

ser.WriteObject(stream1, cn.CompositeNode);

这应该是:

ser.WriteObject(stream1, cn);

顺便说一下,你可以写下这个:

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

您已使用属性定义了已知类型。将已知类型添加到构造函数是多余的。