The deserializer has no knowlege of any type that maps to this contract

前端 未结 3 1151
感情败类
感情败类 2020-12-21 01:46

I\'m trying to serialize and deserialize a tree of Node objects. My abstract \"Node\" class as well as other abstract and concrete classes that derive from it are defined in

3条回答
  •  醉梦人生
    2020-12-21 02:14

    All classes that derive from Node, including Building, have the [KnownType(typeof(type t))] attribute applied to them.

    KnownType is usually applied to the base type - i.e.

    [DataContract, KnownType(typeof(Building)), ...]
    abstract class Node { ... }
    

    (note - you can also specify the known-types in the DataContractSerializer constructor, without requiring attributes)

    EDIT RE YOUR REPLY

    If the framwork class doesn't know about all the derived types, then you need to specify the known types when creating the serializer:

    [DataContract] abstract class SomeBase { }
    [DataContract] class Foo : SomeBase { }
    [DataContract] class Bar : SomeBase { }
    ...
    // here the knownTypes argument is important
    new DataContractSerializer(typeof(SomeBase),
          new Type[] { typeof(Foo), typeof(Bar) });
    

    This can be combined with (for example) preserveObjectReferences etc by replacing the null in the previous example.

    END EDIT

    However, without something reproducible (i.e. Node and Building), it is going to be hard to help much.

    The other odd thing; trees structures are very well suited to things like DataContractSerializer - there is usually no need to flatten them first, since trees can be trivially expressed in xml. Do you really need to flatten it?


    Example:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Runtime.Serialization;
    using System.Xml;
    
    [DataContract, KnownType(typeof(Building))]
    abstract class Node {
        [DataMember]
        public int Foo {get;set;}
    }
    [DataContract]
    class Building : Node {
        [DataMember]
        public string Bar {get;set;}
    }
    
    static class Program
    {
        static void Main()
        {
            Dictionary data = new Dictionary();
            Type type = typeof(Dictionary);
            data.Add(Guid.NewGuid(), new Building { Foo = 1, Bar = "a" });
            StringWriter sw = new StringWriter();
            using (XmlWriter xw = XmlWriter.Create(sw))
            {
                DataContractSerializer dcs = new DataContractSerializer(type);
                dcs.WriteObject(xw, data);
            }
    
            string xml = sw.ToString();
    
            StringReader sr = new StringReader(xml);
            using (XmlReader xr = XmlReader.Create(sr))
            {
                DataContractSerializer dcs = new DataContractSerializer(type);
                Dictionary clone = (Dictionary)
                    dcs.ReadObject(xr);
                foreach (KeyValuePair pair in clone)
                {
                    Console.WriteLine(pair.Key + ": " + pair.Value.Foo + "/" +
                        ((Building)pair.Value).Bar);
                }
            }
        }
    }
    

提交回复
热议问题