【问题标题】:DatacontractSerializer does not serialize base type to inherited typeDatacontractSerializer 不会将基类型序列化为继承类型
【发布时间】:2016-07-12 22:26:39
【问题描述】:

我有一个包含 TimeRanges 集合的 TimeDetails 类。 此类被序列化并存储到数据库。

列表曾经是 DateTimeRange 类型。现在我必须向它添加一个新属性(SomeId)。所以我将它继承到 AvailableTimeRange 并为其添加了 SomeId 属性。 (我必须保留 DateTimeRange 原样,因为它在其他地方使用过。

旧行(具有 DateTimeRange 属性类型)的反序列化失败。

这是我的单元测试

 using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using mynamespace;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void With_DateTimeRange()
        {
            var xml = "<TimeDetails xmlns=\"http://schemas.datacontract.org/2004/07/mynamespace\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
                      "<TimeList>" +
                      "<DateTimeRange><From>2016-01-21T08:00:00</From><To>2016-01-21T11:00:00</To></DateTimeRange>" +
                      "<DateTimeRange><From>2016-07-12T06:00:00</From><To>2016-07-12T09:00:00</To></DateTimeRange>" +
                      "</TimeList>" +
                      "</TimeDetails>";
            TimeDetails details = TimeDetails.FromXml(xml);
           Assert.AreEqual(2, details.TimeList.Count);
        }

        [TestMethod]
        public void With_AvailableTimeRange()
        {
            var xml =
            "<TimeDetails xmlns=\"http://schemas.datacontract.org/2004/07/mynamespace\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">"+
            "<TimeList>"+
            "<AvailableTimeRange><From>2016-07-12T08:00:00</From><SomeId>100</SomeId><To>2016-07-12T09:00:00</To></AvailableTimeRange>"+
            "</TimeList></TimeDetails>";

            var details = TimeDetails.FromXml(xml);
            Assert.AreEqual(1, details.TimeList.Count);
            Assert.IsTrue(details.TimeList[0] is AvailableTimeRange);
            Assert.AreEqual(100, (details.TimeList[0] as AvailableTimeRange).SomeId);
        }
    }
}

namespace mynamespace
{
    public class TimeDetails
    {
        public List<AvailableTimeRange> TimeList { get; set; }

        public static TimeDetails FromXml(string xml)
        {
            if (String.IsNullOrWhiteSpace(xml))
                return null;

            TimeDetails timeDetails;
            byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
            using (MemoryStream ms = new MemoryStream(data))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof (TimeDetails),
                    new[] {typeof (AvailableTimeRange), typeof (DateTimeRange)});
                timeDetails = (TimeDetails) serializer.ReadObject(ms);
            }
            return timeDetails;
        }

    }
    public class DateTimeRange
    {
        public DateTime From { get; set; }
        public DateTime To { get; set; }
    }

    public class AvailableTimeRange : DateTimeRange
    {
        public long? SomeId { get; set; }
    }
}

【问题讨论】:

    标签: inheritance datacontractserializer


    【解决方案1】:

    为了向后兼容,您应该留下DateTimeRange 的列表 - 它可以存储基本类型和派生类型。

    public List<DateTimeRange> TimeList { get; set; }
    

    在 xml 中使用type 属性来识别AvailableTimeRange 实例:

    <DateTimeRange i:type=\"AvailableTimeRange\"><From>2016-07-12T08:00:00</From><To>2016-07-12T09:00:00</To><SomeId>100</SomeId></DateTimeRange>
    

    注意 - xml 中的成员顺序很重要。

    【讨论】:

      猜你喜欢
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-06
      • 1970-01-01
      • 1970-01-01
      • 2018-05-08
      • 1970-01-01
      相关资源
      最近更新 更多