XmlSerializer - произошла ошибка, отражающая тип

Используя C# .NET 2.0, у меня есть класс составных данных, в котором есть атрибут [Serializable]. Я создаю класс XMLSerializer и передаю его в конструктор:

XmlSerializer serializer = new XmlSerializer(typeof(DataClass));

Я получаю исключение:

There was an error reflecting type.

Внутри класса данных есть еще один составной объект. Должен ли он также иметь атрибут [Serializable], или, располагая его на верхнем объекте, он рекурсивно применяет его ко всем объектам внутри?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
346
0
245 405
19
Перейти к ответу Данный вопрос помечен как решенный

Ответы 19

Ответ принят как подходящий

Посмотрите на внутреннее исключение, которое вы получаете. Он сообщит вам, в каком поле / свойстве возникают проблемы с сериализацией.

Вы можете исключить поля / свойства из XML-сериализации, украсив их атрибутом [XmlIgnore].

XmlSerializer не использует атрибут [Serializable], поэтому я сомневаюсь, что проблема в этом.

У моего объекта было поле Uri, которое вызвало это исключение; класс Uri не имеет конструктора без параметров. Спасибо за чаевые.

ford 29.10.2011 01:45

Обнаружил это при поиске в Google - моя конкретная проблема заключалась в том, что свойство в моем классе «быть сериализовано» как IList, когда ему нужно было быть List.

Paul Aldred-Bann 08.10.2012 17:06

Как смотреть на «внутреннее исключение»?

David 17.12.2012 07:47

@David: попробуйте {...} catch (Exception e) {Exception ie = e.InnerException}

Roland 24.04.2013 20:09

или добавьте к часам '@exception'

arolson101 13.06.2013 21:30

Спасибо, этот ответ мне помог. Сначала я посмотрел на внутреннее исключение и просто увидел упоминание об основном классе. Но я понял, что могу углубиться в внутренние исключения из внутренних исключений, и, в конце концов, на 5 уровней ниже я нашел проблему. У меня были противоречивые занятия. Спасибо.

Louis van Tonder 12.07.2013 19:12

так же, как @LouisvanTonder, пришлось пройти несколько внутренних исключений, прежде чем я обнаружил, в каком классе отсутствует пустой конструктор. Спасибо!

theB3RV 04.09.2014 18:17

Спасибо за подсказку @Roland! Я никогда не думал, что у вас есть доступ к этой информации. Очень полезный. Чтобы отладить свою проблему, я распечатал все внутренние исключения следующим образом: try {...} catch (Exception e) {/ * print e.Message * / for (Exception ie = e.InnerException; null! = Ie; ie; ie = ie.InnerException) {/ * распечатать ie.Message * /}}

thehelix 13.12.2014 04:12

@thehelix писать условия йоды не стоит.

ANeves thinks SE is evil 15.12.2014 22:43

@thehelix Я не знаю, буду ли я когда-нибудь использовать ваше выражение «йода», но мне нравится изучать еще один способ делать что-то, спасибо. Но действительно ли вы предлагаете принять InnerException из InnerException? Разве вы не имеете в виду: for(Exception TheExc = e; TheExc != null; TheExc = TheExc.InnerException){print TheExc.Message;} ??

Roland 16.12.2014 01:43

@Roland, я обнаружил три внутренних исключения, детализировав и распечатав все вложенные InnerExceptions. Это выявило некоторую интересную информацию, которая в конечном итоге решила некоторые мои проблемы. Мне нравится выполнять отладку с подробным ведением журнала, поэтому меня это устраивает. :) Выражения Йоды - это у меня привычка, потому что за эти годы я достаточно раз обжигался ошибками присваивания, чтобы больше не тратить время на их отслеживание. Сейчас для меня это происходит автоматически, но я поддерживаю любое соглашение. :)

thehelix 18.12.2014 00:30

@Roland, большое спасибо за то, как проверить внутреннее исключение! У меня было аналогичное исключение, но оказалось, что это было просто потому, что другой мой класс был недоступен из-за его уровня защиты XD ... В общем, этот вопрос действительно помог мне, просто направив меня посмотреть его Внутреннее исключение. Оказывается, перед классом 9.9 просто не хватало «публики».

Kaitlyn 19.09.2015 16:00

У меня было одно из моих свойств как IList, я изменил его на List и wallah!

zish 25.04.2016 02:00

для меня это было то, что у меня были [XmlArray] и [XmlArrayItem(typeof(Column))] над свойством без списка

MistaGoustan 15.03.2019 19:51

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

Все объекты в графе сериализации должны быть сериализуемыми.

Поскольку XMLSerializer является черным ящиком, проверьте эти ссылки, если вы хотите продолжить отладку в процессе сериализации.

Изменение того, где XmlSerializer выводит временные сборки

КАК: Отладка в сгенерированной сборке .NET XmlSerializer

Я тоже думал, что атрибут Serializable должен быть на объекте, но если я не являюсь полным нубом (я нахожусь в середине ночного сеанса кодирования), следующие работы из SnippetCompiler:

using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using System.Xml.Serialization;

public class Inner
{
    private string _AnotherStringProperty;
    public string AnotherStringProperty 
    { 
      get { return _AnotherStringProperty; } 
      set { _AnotherStringProperty = value; } 
    }
}

public class DataClass
{
    private string _StringProperty;
    public string StringProperty 
    { 
       get { return _StringProperty; } 
       set{ _StringProperty = value; } 
    }

    private Inner _InnerObject;
    public Inner InnerObject 
    { 
       get { return _InnerObject; } 
       set { _InnerObject = value; } 
    }
}

public class MyClass
{

    public static void Main()
    {
        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(DataClass));
            TextWriter writer = new StreamWriter(@"c:\tmp\dataClass.xml");
            DataClass clazz = new DataClass();
            Inner inner = new Inner();
            inner.AnotherStringProperty = "Foo2";
            clazz.InnerObject = inner;
            clazz.StringProperty = "foo";
            serializer.Serialize(writer, clazz);
        }
        finally
        {
            Console.Write("Press any key to continue...");
            Console.ReadKey();
        }
    }

}

Я бы предположил, что XmlSerializer использует отражение над общедоступными свойствами.

Помните, что сериализованные классы должны иметь конструкторы по умолчанию (т.е. без параметров). Если у вас вообще нет конструктора, ничего страшного; но если у вас есть конструктор с параметром, вам также нужно добавить конструктор по умолчанию.

Спасибо за напоминание! Ненавижу, что это ошибка времени выполнения без небольшого объяснения.

Jared Updike 18.11.2008 02:33

Я повторяю эту ошибку снова и снова. спасибо, что напомнили мне использовать конструктор без параметров ^^

aZtraL-EnForceR 31.05.2014 23:50

Также имейте в виду, что XmlSerializer не может сериализовать абстрактные свойства .. См. Мой вопрос здесь (в который я добавил код решения) ..

Сериализация XML и унаследованные типы

Я использовал класс NetDataSerialiser для сериализации мои доменные классы. Класс NetDataContractSerializer.

Классы домена разделяются между клиентом и сервером.

Я обнаружил, что класс Dictionary в .Net 2.0 не сериализуется с помощью XML, но хорошо сериализуется при использовании двоичной сериализации.

Я нашел работу вокруг здесь.

Если вам нужно обрабатывать определенные атрибуты (например, словарь или любой класс), вы можете реализовать интерфейс IXmlSerialiable, который предоставит вам больше свободы за счет более подробного кодирования.

public class NetService : IXmlSerializable
{
    #region Data

        public string Identifier = String.Empty;

        public string Name = String.Empty;

        public IPAddress Address = IPAddress.None;
        public int Port = 7777;

    #endregion

    #region IXmlSerializable Implementation

        public XmlSchema GetSchema() { return (null); }

        public void ReadXml(XmlReader reader)
        {
            // Attributes
            Identifier = reader[XML_IDENTIFIER];
            if (Int32.TryParse(reader[XML_NETWORK_PORT], out Port) == false)
            throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_PORT);
            if (IPAddress.TryParse(reader[XML_NETWORK_ADDR], out Address) == false)
            throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_ADDR);
        }

        public void WriteXml(XmlWriter writer)
        {
            // Attributes
            writer.WriteAttributeString(XML_IDENTIFIER, Identifier);
            writer.WriteAttributeString(XML_NETWORK_ADDR, Address.ToString());
            writer.WriteAttributeString(XML_NETWORK_PORT, Port.ToString());
        }

        private const string XML_IDENTIFIER = "Id";

        private const string XML_NETWORK_ADDR = "Address";

        private const string XML_NETWORK_PORT = "Port";

    #endregion
}

Есть интересный статья, который демонстрирует элегантный способ реализации изощренного способа «расширения» XmlSerializer.


В статье говорится:

IXmlSerializable is covered in the official documentation, but the documentation states it's not intended for public use and provides no information beyond that. This indicates that the development team wanted to reserve the right to modify, disable, or even completely remove this extensibility hook down the road. However, as long as you're willing to accept this uncertainty and deal with possible changes in the future, there's no reason whatsoever you can't take advantage of it.

Поэтому я предлагаю реализовать собственные классы IXmlSerializable, чтобы избежать слишком сложных реализаций.

... может быть просто реализовать наш собственный класс XmlSerializer с помощью отражения.

Я недавно получил это в частичном классе веб-ссылки при добавлении нового свойства. Автоматически созданный класс добавлял следующие атрибуты.

    [System.Xml.Serialization.XmlElementAttribute(Order = XX)]

Мне нужно было добавить аналогичный атрибут с порядком выше последнего в автоматически сгенерированной последовательности, и это исправило его для меня.

У меня была аналогичная проблема, и оказалось, что сериализатор не мог различить 2 класса, которые у меня были с тем же именем (один был подклассом другого). Внутреннее исключение выглядело так:

Оба типа «BaseNamespace.Class1» и «BaseNamespace.SubNamespace.Class1» используют имя типа XML «Class1» из пространства имен «». Используйте атрибуты XML, чтобы указать уникальное имя XML и / или пространство имен для типа.

Где BaseNamespace.SubNamespace.Class1 является подклассом BaseNamespace.Class1.

Что мне нужно было сделать, так это добавить атрибут к одному из классов (я добавил к базовому классу):

[XmlType("BaseNamespace.Class1")]

Примечание. Если у вас есть несколько уровней классов, вам также необходимо добавить к ним атрибут.

Это решило проблему для меня, спасибо, +1; У меня была аналогичная настройка с несколькими объектами Processor *, каждый из которых имел внутренний класс Config. Среда выполнения не смогла различить SomeNS.Processor1.Config и SomeNS.Processor2.Config.

damix911 04.06.2012 00:38

Я получил ту же ошибку и обнаружил, что проблема в свойстве типа IEnumerable<SomeClass>. Похоже, что IEnumerable нельзя сериализовать напрямую.

Вместо этого можно было использовать List<SomeClass>.

У меня была ситуация, когда порядок был одинаковым для двух элементов подряд

[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")]

.... какой-то код ...

[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")]

Когда я изменил код, чтобы увеличить порядок на единицу для каждого нового свойства в классе, ошибка исчезла.

Наиболее частые причины на мой взгляд:

 - the object being serialized has no parameterless constructor
 - the object contains Dictionary
 - the object has some public Interface members

[System.Xml.Serialization.XmlElementAttribute("strFieldName", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]

Или же

[XmlIgnore]
string [] strFielsName {get;set;}

У меня была такая же проблема, и в моем случае объект имел ReadOnlyCollection. Для сериализации коллекция должна реализовывать метод Add.

Это неправильный ответ на вопрос. На этот вопрос уже есть еще 15 ответов. Если вы считаете, что ваш ответ лучше других, вы должны предоставить о нем более подробную информацию. Предоставление кода и фрагментов вывода всегда помогает пользователям. Перед тем, как публиковать свои ответы, подумайте о прочтении -> stackoverflow.com/help/how-to-answer

Amit Phaltankar 26.05.2017 04:59

У меня есть несколько иное решение, чем все описанное здесь, так что для любой будущей цивилизации вот мое!

Я объявил тип данных «время», поскольку исходным типом был TimeSpan, который впоследствии был изменен на String:

[System.Xml.Serialization.XmlElementAttribute(DataType = "time", Order=3)]

однако фактический тип был строкой

public string TimeProperty {
    get {
        return this.timePropertyField;
    }
    set {
        this.timePropertyField = value;
        this.RaisePropertyChanged("TimeProperty");
    }
}

удалив свойство DateType, можно сериализовать Xml

[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string TimeProperty {
    get {
        return this.timePropertyField;
    }
    set {
        this.timePropertyField = value;
        this.RaisePropertyChanged("TimeProperty");
    }
}

Я получал ту же ошибку, когда создавал свойство с типом данных - Type. По этому я получал ошибку - Произошла ошибка, отражающая тип. Я продолжал проверять «InnerException» каждого исключения из док-станции отладки и получил конкретное имя поля (которое было Type) в моем случае. Решение такое:

    [XmlIgnore]
    public Type Type { get; set; }

Иногда этот тип ошибки возникает из-за того, что у вас нет конструктора класса без аргумента.

Другие вопросы по теме