【问题标题】:Serialization of class derived from List<> using DataContract使用 DataContract 对从 List<> 派生的类进行序列化
【发布时间】:2010-08-07 19:55:48
【问题描述】:

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

我的课:

[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],在序列化过程中抛出异常(集合不能使用该属性)

顺便说一句,我也在序列化私有字段,所以我不能使用XmlSerializer(或其他不能序列化私有字段的类)。

【问题讨论】:

    标签: c# serialization datacontract


    【解决方案1】:

    改为使用 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; }
    

    【讨论】:

    • 不,这不是我需要的。我序列化DownloadRule 类没有问题,序列化DownloadRuleCollection 本身有问题,尤其是它的属性。
    【解决方案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);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-29
      • 2015-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多