从List<>派生的类的序列化使用DataContract

时间:2010-08-07 19:55:49

标签: c# serialization datacontract

我正在尝试序列化从List<>派生的类使用DataContract。问题是我的类的属性不会被序列化。

我的课程:

[CollectionDataContract] /*[Serializable]*/ /*[DataContract]*/
public class DownloadRuleCollection : List<DownloadRule> {

    [DataMember(EmitDefaultValue = false)]
    public string SomeProperty { get; set; }
    //this is, in fact, more complex, but this is enough for the example
}

[DataContract]
public class DownloadRule {
    [DataMember(EmitDefaultValue = false)]
    public string Name { get; set; }

    /*
     more properties
     ...
     */
}

测试:

static void Main(string[] args) {

    //fill test collection with some data...
    var col = new DownloadRuleCollection { SomeProperty = "someText" };

    var rule = new DownloadRule { Name = "test01" };
    col.Add(rule);

    rule = new DownloadRule { Name = "test02" };
    col.Add(rule);

    rule = new DownloadRule { Name = "test03" };
    col.Add(rule);

    //serialize
    Console.WriteLine("serializing");

    Serialize(col, "serializationTest.xml");

    Console.WriteLine("serialized");
    Console.ReadLine();
}

结果:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfDownloadRule xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication1">
  <DownloadRule>
    <Name>test01</Name>
  </DownloadRule>
  <DownloadRule>
    <Name>test02</Name>
  </DownloadRule>
  <DownloadRule>
    <Name>test03</Name>
  </DownloadRule>
</ArrayOfDownloadRule>

如您所见,List的项目已正确序列化(和反序列化),但List本身不会被序列化。我试图使用不同的属性:
[Serializable],没有变化;
[DataContract],在序列化期间抛出异常(集合无法使用此属性)

btw我正在序列化私有字段,所以我不能使用XmlSerializer(或其他不能序列化私有字段的类)。

3 个答案:

答案 0 :(得分:2)

请改用IList。这应该正确序列化。

    [CollectionDataContract] /*[Serializable]*/ /*[DataContract]*/
    public class DownloadRuleCollection : IList<DownloadRule> {

以下是我使用并完美运作的示例:

    [DataContract(Namespace="http://schemas.datacontract.org/2004/07/InboundIntegration.HL7Messaging")]
    public class Message {

        public Message() {
            InsuranceList = new List<Insurance>();
            MessageId = GuidComb.NewGuid();
        }

        [IgnoreDataMember]
        public Guid MessageId { get; private set; }

        #region "Data"
        [DataMember]
        public string MessageTypeIndicator { get; set; }
        [DataMember]
        public MessageConfiguration MessageConfiguration { get; set; }
        [DataMember]
        public Patient Patient { get; set; }
        [DataMember]
        public Encounter Encounter { get; set; }
        [DataMember]
        public IList<Insurance> InsuranceList { get; set; }
        #endregion

然后保险类看起来像这样:

 [DataContract(Namespace = "http://schemas.datacontract.org/2004/07/InboundIntegration.HL7Messaging")]
    public class Insurance {
        [DataMember]
        public string ExternalPayerId { get; set; } 
        [DataMember]
        public string PayerName { get; set; }
        [DataMember]
        public string GroupNumber { get; set; }
        [DataMember]
        public string MemberIdOfPatient { get; set; }
        [DataMember]
        public string PatientRelationshipToInsuredIndicator { get; set; }
        [DataMember]
        public string CoordinationOfBenefitsPrecedenceIndicator { get; set; }

答案 1 :(得分:2)

好的,所以Climber104的解决方案可行,但我需要重新实现所有List的方法,这让我觉得我正在重新发明轮子。

来自Jarek Waliszko的JaredPar建议使用包装类 最简单的方法就是为了序列化过程而使用它,所以我使用了一个受保护的内包装类。这使我能够通过几行代码实现我的目标。

public class DownloadRuleCollection : List<DownloadRule> {

    public string SomeProperty { get; set; }

    public void Serialize(string fileName) {
        Serializer.Serialize(
            new DownloadRuleCollection_SerializationWrapper {
                Collection = this,
                SomeProperty = SomeProperty
            }, fileName);
    }

    public static DownloadRuleCollection Deserialize(string fileName) {
        var wrapper = Serializer.Deserialize<DownloadRuleCollection_SerializationWrapper>(fileName);

        var result = wrapper.Collection;
        result.SomeProperty = wrapper.SomeProperty;

        return result;
    }

    [DataContract(Name = "DownloadRuleCollection")]
    private class DownloadRuleCollection_SerializationWrapper {

        [DataMember(EmitDefaultValue = false, Name = "SomeProperty", Order = 0)]
        public string SomeProperty { get; set; }

        [DataMember(EmitDefaultValue = false, Name = "DownloadRules", Order = 1)]
        public DownloadRuleCollection Collection;

    }
}

[DataContract]
public class DownloadRule {
    [DataMember(EmitDefaultValue = false)]
    public string Name { get; set; }
}

public static class Serializer {
    public static void Serialize<T>(T obj, string fileName) {
        using(XmlWriter writer = XmlWriter.Create(fileName, new XmlWriterSettings { Indent = true }))
            new DataContractSerializer(typeof(T)).WriteObject(writer, obj);
    }

    public static T Deserialize<T>(Stream stream) {
        return (T)new DataContractSerializer(typeof(T)).ReadObject(stream);
    }

    public static T Deserialize<T>(string fileName) {
        using(FileStream fs = File.OpenRead(fileName)) {
            return Deserialize<T>(fs);
        }
    }
}

答案 2 :(得分:1)

检查帖子,我相信它可以帮到你

c# inheriting generic collection and serialization