2013-12-12 5 views
0

Так это был я в тупик в течение нескольких часов ... У меня есть структуру XML, которая выглядит следующим образом:XmlSerializer.Deserialize для класса к югу (не массив)

<custom> 
    <priceLower>999999</priceLower> 
    <priceUpper>1000001</priceUpper> 
    <investment>true</investment> 
    <offtheplan>false</offtheplan> 
    <office> 
    <name>Melbourne Office</name> 
    <officeName>Head Office</officeName> 
    ... more elements removed 
    </office> 
</custom> 

В моем приложении у меня есть Выборочный класс, который десериализует из приведенного выше XML штрафа, определяется следующим образом:

[Serializable] 
public class Custom : BaseEntity, IDataModel 
{ 
    [XmlElement("investment")] 
    public string Investment { get; set; } 
    [XmlElement("offtheplan")] 
    public string Offtheplan { get; set; } 
    [XmlElement("priceLower")] 
    public Decimal? PriceLower { get; set; } 
    [XmlElement("priceUpper")] 
    public Decimal? PriceUpper { get; set; } 
    [XmlElement("office")] 
    public Office Office { get; set; } 

И мой офис объекта определяется следующим образом:

[Serializable] 
public class Office : BaseEntity, IDataModel 
{ 
    // temporary for debugging purposes: 
    private string _officeName; 

    [XmlElement("name")] 
    public string Name { get; set; } 
    [XmlElement("officeName")] 
    public string OfficeName { get; set; } 
    [XmlElement("addressL1")] 
    public string Address1 { get; set; } 
    ... more fields removed } 

Код десериализации (вызывается вспомогательный класс, и получает объект недвижимости, содержащий пользовательский объект, который содержит объект офис) выглядит следующим образом:

  XmlSerializer s = null; 
    XmlAttributeOverrides attrOverrides = null; 

      /// if it's a Residential type, do it this way 
      if (typeof(T) == typeof(Residential)) 
      { 
       attrOverrides = new XmlAttributeOverrides(); 
       var attrs = new XmlAttributes(); 
       var attr = new XmlElementAttribute(); 
       attr.ElementName = "office"; 
       attr.Type = typeof(Office); 
       attrs.XmlElements.Add(attr); 
       attrOverrides.Add(typeof(Office), "office", attrs); 
       s = new XmlSerializer(typeof(T), attrOverrides); 
      } 

      s = attrOverrides == null 
       ? new XmlSerializer(typeof(T)) 
       : new XmlSerializer(typeof(T), attrOverrides); 

      var obj = s.Deserialize(stream); 
      return (T)obj; 

SO ... Пользовательский объект десериализует совершенно .. нет вопросы там. Но в офисе нет - все его свойства всегда проходят через нуль.

Есть ли способ указать, какой именно элемент в дереве xml содержит данные для объекта Office? я попытался переместить объект Office, чтобы сидеть на том же уровне, что и Custom (в объекте Property), который имеет больше смысла, но это тоже не сработало - я переместил его под Custom, чтобы он соответствовал структуре xml, поскольку я не может изменить это, и я не мог найти способ указать, откуда он должен получить свои данные.

Еще одна странность, которую я испытал здесь ... Я добавил функцию Serializer, которая в основном создает новый XML-файл из десериализованных объектов. Я могу отлаживать весь путь до того, как вызывается функция Serialize, и если я заглядываю внутрь объекта, который будет сериализован до его появления, я вижу, что объект Office содержит только нулевые значения. Но сериализатор фактически сериализует данные в мой новый XML-файл.

Здесь он становится еще более странным. Если я заглядываю в объект до вызова Serialize(), он всегда будет сериализовать пустой элемент. НО, если я не заглядываю внутрь этого объекта до того, как произойдет сериализация, он будет сериализовать данные там. Я проверил это несколько раз - непременно это поведение. Кто-нибудь когда-нибудь видел что-то подобное? Является ли фреймворк трюками для меня, и если так, то?

UPDATE:

Просто чтобы прояснить, мой XML выглядит примерно так (я только показал Exert выше):

<propertyList> 
    <residential> 
    <custom> 
     <property1> 
     <office> 
     <officeName> 
      Office Name Here 
     </officeName> 
     </office> 
    </custom> 
    </residential> 
</propertyList> 

Так что есть несколько уровней вложенности там, что я, возможно, этот вопрос , хотя я думаю, что это скорее проблема VS.

десериализатор работает на полную XML, и deserialising вплоть до классовой структуры, как это:

жилая: Недвижимость BasePropertyType

  • Содержит пользовательский объект
  • содержит Офис Объект

Объекты Custom и Office создаются на объекте Residential. Я попытался вместо этого поставить объект Office на пользовательский объект (чтобы соответствовать структуре xml), но это не имело никакого значения. Пользовательский сериализуется правильно, Office не работает.

Возможно ли, что отладчик Visual Studio является красной селедкой здесь. Как я уже упоминал ранее, если я отлаживаю и смотрю на десериализованный объект, он показывает его как пустым, и когда я затем сериализую его обратно в XML, он становится пустым. Но если я не отлаживаю и не перешагиваю, не обращая внимания на объект, все свойства корректно сериализуются в XML. Это делает его трудным для перехода на другую и обрабатывать всю необходимую обработку данных, когда я не могу отлаживать то, что там происходит. Кто-нибудь видел поведение в VS, как это раньше?

ответ

0

Ахахахаха ... Я такой лох! Имел напарнику бежать через это со мной, и мы нашли что-то действительно глупо, что я сделал, а именно:

public string ToString() 
{ 
    Name = null; 
    OfficeName = null; 
    Address1 = null; 
    Address2 = null; 
    City = null; 
    State = null; 
    Postcode = null; 
    Phone = null; 
    Banner = null; 
    Logo = null; 

    StringBuilder sb = new StringBuilder(); 
    sb.Append(String.Format("Name:{0}/OfficeName: {1}/Address1: {2}/Address2: {3}/City: {4}/State: {5}/Postcode: {6}/Phone: {7}/Banner: {8}/Logo: {9}", 
     Name, OfficeName, Address1, Address2, City, State, Postcode, Phone, Banner, Logo)); 
    return sb.ToString(); 
} 

Таким образом, каждый раз, когда я посмотрел на объект в отладчик, он звонит мой ToString () override, который затем уничтожал все значения.

Не чувствую себя застенчивым. LOL

0

Что касается первого вопроса, то XmlSerializer может обрабатывать простые иерархий поэтому в вашем примере XmlAttributeOverrides не нужны:

[Serializable] 
    [XmlRoot("custom")] 
    public class Custom 
    { 
     [XmlElement("investment")] 
     public string Investment { get; set; } 
     [XmlElement("offtheplan")] 
     public string Offtheplan { get; set; } 
     [XmlElement("priceLower")] 
     public Decimal? PriceLower { get; set; } 
     [XmlElement("priceUpper")] 
     public Decimal? PriceUpper { get; set; } 
     [XmlElement("office")] 
     public Office Office { get; set; } 
    } 

    [Serializable] 
    public class Office 
    { 
     // temporary for debugging purposes: 
     private string _officeName; 

     [XmlElement("name")] 
     public string Name { get; set; } 
     [XmlElement("officeName")] 
     public string OfficeName { get; set; } 
     [XmlElement("addressL1")] 
     public string Address1 { get; set; } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      string xml = @"<custom> 
    <priceLower>999999</priceLower> 
    <priceUpper>1000001</priceUpper> 
    <investment>true</investment> 
    <offtheplan>false</offtheplan> 
    <office> 
    <name>Melbourne Office</name> 
    <officeName>Head Office</officeName> 
    </office> 
</custom>"; 

      XmlSerializer s = new XmlSerializer(typeof(Custom)); 

      // Works fine without this 
      //XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides(); 
      //var attrs = new XmlAttributes(); 
      //var attr = new XmlElementAttribute(); 
      //attr.ElementName = "office"; 
      //attr.Type = typeof(Office); 
      //attrs.XmlElements.Add(attr); 
      //attrOverrides.Add(typeof(Office), "office", attrs); 
      //s = new XmlSerializer(typeof(Custom), attrOverrides); 

      using (StringReader reader = new StringReader(xml)) 
      { 
       Custom c = (Custom)s.Deserialize(reader); 
      } 
     } 
    } 
+0

Хорошо, когда вы говорите, что он может обрабатывать «простые иерархии» ... означает ли это, что он не может обработать структуру, которую я пытаюсь сериализовать (т. Е. 3 уровня в глубину)? Я не могу найти никакой документации вокруг этого типа структуры в любом месте, за исключением коллекций (которых у меня нет). – Jeeby

+0

Нет, я не думаю, что глубина проблемы (например, код, который я опубликовал, имеет 3 уровня глубины и отлично работает). Это что-то еще - может быть, ваш базовый класс? Или отсутствующий конструктор без параметров в классе Office? Можете ли вы отредактировать сообщение, чтобы включить SSCCE (или отправить его на GitHub)? – Dusan

+0

В офисном классе определенно есть беззаботный конструктор (просто устанавливает все в нуль, что и заканчивается). Что такое SSCCE? – Jeeby

Смежные вопросы