2016-07-12 5 views
0

У меня есть класс TimeDetails, в котором есть коллекция TimeRanges. Этот класс сериализуется и хранится в DB.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