有没有办法使用DataContractSerializer序列化包含抽象类型的Dictionary?

时间:2016-03-30 17:40:45

标签: c# .net serialization

例如

[DataContract]
public abstract class BaseClass
{
    public abstract string id { get; set; }
}

[DataContract(Name = "class1")]
public class concreteClass1 : BaseClass
{
    public concreteClass1() { }

    [DataMember]
    public override string id { get; set; }

    [DataMember]
    public string prop1 { get; set; }

    [DataMember]
    public string prop2 { get; set; }

}

[DataContract(Name = "class2")]
public class concreteClass2 : BaseClass
{
    public concreteClass2() { }

    [DataMember]
    public override string id { get; set; }

    [DataMember]
    public string prop1 { get; set; }

    [DataMember]
    public string prop2 { get; set; }

}

当我尝试序列化包含其中一个具体类的字典时,如

static public void Main(string[] args){

    Dictionary<string, BaseClass> items = new Dictionary<string, BaseClass>();
    items.Add("1", new concreteClass1() { id = "1", prop1 = "blah1" });
    items.Add("11", new concreteClass1() { id = "11", prop1 = "blah11" });

    var serializer = new DataContractSerializer(items.GetType());
    string xmlString = string.Empty;
    using (var sw = new StringWriter())
    {
        using (var writer = new XmlTextWriter(sw))
        {
            writer.Formatting = System.Xml.Formatting.Indented;
            serializer.WriteObject(writer, items );
            writer.Flush();
            xmlString = sw.ToString();
        }
    }

}

尝试WriteObject时出现此错误

  

键入&#39; ConsoleTest.Program + Base&#39;无法序列化。考虑标记   它与DataContractAttribute属性,并标记其所有   要使用DataMemberAttribute属性序列化的成员。   如果类型是集合,请考虑使用   CollectionDataContractAttribute。请参阅Microsoft .NET Framework   其他支持类型的文档。

有没有办法解决这个问题?

编辑:我也尝试在基类上使用KnownType但它没有工作

    [DataContract]
    [KnownType(typeof(concreteClass1))]
    [KnownType(typeof(concreteClass2))]
    public abstract class BaseClass
    {
        public abstract string id { get; set; }
    }

1 个答案:

答案 0 :(得分:1)

试试这个......

使用....

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;

班级......

[DataContract]
[KnownType(typeof(concreteClass1))]
[KnownType(typeof(concreteClass2))]
public abstract class BaseClass
{
    [DataMember]
    public abstract string id { get; set; }
}

[DataContract(Name = "class1")]
public class concreteClass1 : BaseClass
{
    public concreteClass1() { }

    [DataMember]
    public override string id { get; set; }

    [DataMember]
    public string prop1 { get; set; }

    [DataMember]
    public string prop2 { get; set; }

}

[DataContract(Name = "class2")]
public class concreteClass2 : BaseClass
{
    public concreteClass2() { }

    [DataMember]
    public override string id { get; set; }

    [DataMember]
    public string prop1 { get; set; }

    [DataMember]
    public string prop2 { get; set; }

}

代码。

    static void Main(string[] args)
    {
        Dictionary<string, BaseClass> items = new Dictionary<string, BaseClass>();
        items.Add("1", new concreteClass1() { id = "1", prop1 = "blah1" });
        items.Add("11", new concreteClass1() { id = "11", prop1 = "blah11" });
        // this should work too....
        items.Add("999", new concreteClass2() { id = "999", prop1 = "blah999" });
        items.Add("888", new concreteClass2() { id = "888", prop1 = "blah888" });

        //Serialize(items);

        var serializer = new DataContractSerializer(items.GetType());
        string xmlString = string.Empty;
        try
        {
            using (var sw = new StringWriter())
            {
                using (var writer = new XmlTextWriter(sw))
                {
                    writer.Formatting = System.Xml.Formatting.Indented;
                    serializer.WriteObject(writer, items);
                    writer.Flush();
                    xmlString = sw.ToString();
                }
            }
        }
        catch (Exception)
        {

            throw;
        }
    }

///////////////////// UPDATE /////////////////////

作为一点奖励(我觉得我没有看到我的25分)这里有两个函数可以序列化和反序列化一个通用对象......

        public static void Serialize<T>(T data)
        {
            try // try to serialize the collection to a file
            {
                using (Stream  stream = File.Open("data.xml", FileMode.Create))
                {
                    // create DataContractSerializer
                    DataContractSerializer serializer = new DataContractSerializer(typeof (T));
                    // serialize the collection (EmployeeList1) to file (stream)
                    serializer.WriteObject(stream, data);
                }
            }
            catch (IOException)
            {
            }
        }

        public static T Deserialize<T>() where T : new()
        {
            // Create an instance of T
            T ReturnListOfT = CreateInstance<T>();

            // Try to Deserialize from file stream
            try
            {
                using (Stream stream = File.Open("data.xml", FileMode.Open))
                {
                    // create DataContractSerializer
                    DataContractSerializer serializer = new DataContractSerializer(typeof (T));
                    // deserialize the collection (Employee) from file (stream)
                    ReturnListOfT = (T)serializer.ReadObject(stream);
                }
            }
            catch (IOException)
            {
            }

            return (T)ReturnListOfT;
        }

        // function to create instance of T
        public static T CreateInstance<T>() where T : new()
        {
            return (T)Activator.CreateInstance(typeof(T));
        }

而不是必须手动修改XML,您可以使用现有类反序列化对象(来自文件,在示例'data.xml'中)并创建用户界面以允许用户修改属性object \ classes,然后将修改后的对象重新保存\序列化回文件.....

相关问题