Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WinForms, .Net Framework Новый топик    Ответить
 XmlSerializer+base class+XmlTextAttribute - InvalidOperationException  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6154
Дано (в сжатом виде):
1. Примерно такая схема:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="item">
          <xs:complexType>
            <xs:simpleContent>
              <xs:extension base="xs:int">
                <xs:attribute name="name" type="xs:string" use="required" />
                <xs:attribute name="type" type="xs:string" use="required" />
              </xs:extension>
            </xs:simpleContent>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

В реальной рабочей схеме имеется куча объявленных xs:complexType c одинаковым набором атрибутов, эти типы отличаются только базой контента.
2. На основании схемы генерим с пом. xsd.exe класс, слегка дорабатываем напильником:
[System.Serializable]
[XmlType(AnonymousType = true)]
[XmlRoot(ElementName = "root", Namespace = "", IsNullable = false)]
public class Root
{
  [XmlElement("item")]
  public RootItem Item { get; set; }
}

[System.Serializable]
[XmlType(AnonymousType = true)]
public class RootItem
{
  [XmlAttribute("name")]
  public string Name { get; set; }
  [XmlAttribute("type")]
  public string Type { get; set; }
  [XmlText]
  public int Value { get; set; }
}

пробуем делать десериализацию:
try
{
  using (var sr = new StringReader("<root><item name='foo' type='bar'>123</item></root>"))
  {
    if (!(new XmlSerializer(typeof(Root)).Deserialize(sr) is Root r))
      throw new InvalidOperationException("Not instace of Root");
    Console.WriteLine(r);
  }
}
catch(Exception e)
{
  Console.WriteLine(e);
}

- всё ок. Теперь, поскольку см. выше про кучу типов с одинаковым набором атрибутов, меняем класс RootItem так:
public class RootItemBase
{
  [XmlAttribute("name")]
  public string Name { get; set; }
  [XmlAttribute("type")]
  public string Type { get; set; }
}

[System.Serializable]
[XmlType(AnonymousType = true)]
public class RootItem : RootItemBase
{
  [XmlText]
  public int Value { get; set; }
}

и при десериализации ловим:

System.InvalidOperationException: There was an error reflecting type 'test2.Root'.
---> System.InvalidOperationException: There was an error reflecting property 'Item'.
---> System.InvalidOperationException: There was an error reflecting type 'test2.RootItem'.
---> System.InvalidOperationException: Cannot serialize object of type 'test2.RootItem'.
Consider changing type of XmlText member 'test2.RootItem.Value' from System.Int32 to string or string array.

Я, конечно, могу это свойство сделать стринговым, и дополнительно завести вычисляемое на основе Value числовое свойство с XmlIgnore - но какого? Почему наличие базового класса ломает сериализацию XmlText? Что не так?
И да, методом научного тыка выяснилось, что для воспроизведения ошибки достаточно, чтобы сериализумый класс просто наследовался от чего-нибудь, отличного от object - т.е. аналогичная ошибка будет и вот в такоим случае:
public class RootItemBase
{
}

[System.Serializable]
[XmlType(AnonymousType = true)]
public class RootItem : RootItemBase
{
  [XmlAttribute("name")]
  public string Name { get; set; }
  [XmlAttribute("type")]
  public string Type { get; set; }
  [XmlText]
  public int Value { get; set; }
}

Это вообще можно как-нибудь побороть?
30 мар 21, 06:45    [22301790]     Ответить | Цитировать Сообщить модератору
 Re: XmlSerializer+base class+XmlTextAttribute - InvalidOperationException  [new]
ЕвгенийВ
Member

Откуда: Москва
Сообщений: 4972
Сон Веры Павловны,
не поможет?
https://docs.microsoft.com/ru-ru/dotnet/api/system.xml.serialization.xmlincludeattribute?view=net-5.0
30 мар 21, 12:13    [22301934]     Ответить | Цитировать Сообщить модератору
 Re: XmlSerializer+base class+XmlTextAttribute - InvalidOperationException  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6154
ЕвгенийВ
Сон Веры Павловны,
не поможет?
https://docs.microsoft.com/ru-ru/dotnet/api/system.xml.serialization.xmlincludeattribute?view=net-5.0

Спасибо, но увы, не помогло.
Выяснилось, что это достаточно известный баг - известный в т.ч. разработчикам дотнета. Ответ от них тоже стандартный: да, знаем, раз пути обхода (в виде decorated properties) есть, то исправлять не будем, а то очень дофига придётся исправлять: https://github.com/dotnet/runtime/issues/22656
Значит, придётся использовать эти decorated properties.
30 мар 21, 13:28    [22301994]     Ответить | Цитировать Сообщить модератору
Все форумы / WinForms, .Net Framework Ответить