2016-07-12 127 views
0

我有一個TimeDetails類,它具有TimeRanges集合。 該類被序列化並存儲到數據庫。DatacontractSerializer不會將基類型序列化爲繼承類型

該列表曾經是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; } 
    } 
} 

回答

0

爲了向後兼容,你應該離開的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是很重要的。

+0

工作!非常感謝 – user2100334