Почему XmlSerializer настолько трудно использовать?

Я воображаю для использования сериализации XML как это:

class Foo {
    public Foo (string name) {
        Name1 = name;
        Name2 = name;
    }

    [XmlInclude]
    public string Name1 { get; private set; }

    [XmlInclude]
    private string Name2;
}

StreamWriter wr = new StreamWriter("path.xml");
new XmlSerializer<Foo>().Serialize (wr, new Foo ("me"));

Править: Я знаю, что этот код является неверным. Это должно было только отобразиться, как я хотел бы использовать его.

Но это не работает вообще:

  • XmlSerializer не универсален. Я должен бросить от и возразить на (de) сериализации.
  • Каждая собственность должна быть полностью общественной. Почему мы не просто использование Отражения для доступа к частным методам set?
  • Частные поля не могут быть сериализированы. Я хотел бы украсить частные поля атрибутом, чтобы сделать, чтобы XmlSerializer включал их.

Я пропускал что-то, и XmlSerializer на самом деле предлагает описанные возможности? Там чередуйтесь, сериализаторы к XML, которые обрабатывают эти случаи более сложно?

Если нет: мы в 2010, в конце концов, и.NET была вокруг много лет. Сериализация XML часто используется, полностью стандартная и должна быть действительно легкой работать. Или мое понимание возможно неправильно, и сериализация XML не должна выставлять описанные функции серьезного основания?

Править: Наследие не является серьезным основанием imo. Listбыло неуниверсально сначала, также.

(Не стесняйтесь корректировать подпись или теги. Если это должно быть CW, просто напишите.)

8
задан mafu 23 March 2010 в 15:55
поделиться

5 ответов

Сначала фиксированный код, затем ответы на ваши вопросы:

public class Foo {
    public Foo() : this("") {}
    public Foo (string name) {
        Name1 = name;
        Name2 = name;
    }
    // note only this will be serialized
    public string Name1 { get; private set; }
    // this won't
    private string Name2;
}

или в версии 3.0:

[DataContract]
class Foo {
    public Foo (string name) {
        Name1 = name;
        Name2 = name;
    }
    [DataMember]
    public string Name1 { get; private set; }
    [DataMember]
    private string Name2;
}

(и используйте DataContractSerializer вместо XmlSerializer )

XmlSerializer не является универсальным. Мне нужно выполнить приведение из и в объект при (де) сериализации.

Это обычное дело для сериализаторов. У меня есть собственный сериализатор, и изначально я сделал полностью универсальным. И это оказалось большой дизайнерской ошибкой. Огромный. Нет, серьезно. В настоящее время я переписываю каждую строчку кода, чтобы отключить ее.

Просто; сериализаторы обычно включают некоторый уровень отражения (либо для генерации кода, либо для фактической работы, в зависимости от реализации). Отражение и обобщения не очень хорошо работают, особенно на некоторых фреймворках, таких как WCF. Окончательное приведение кода к вашему коду - это справедливый компромисс. У меня есть число записей в блоге, если вы действительно хотите ...

Каждая собственность должна быть полностью общедоступной.

Это действительно ограничение XmlSerializer (хотя список / сборник без сеттера вполне допустим, он будет сгенерирован, если у вас есть общедоступное получение и частный набор). Кроме того, тип должен быть общедоступным и иметь конструктор без параметров.

Почему мы просто не используем Reflection для доступа к частным сеттерам?

Для повышения производительности XmlSerializer создает сборку на лету, чтобы делать то, что вы хотите. У него нет автоматического доступа к внутреннему устройству вашего кода. Для информации, я делаю нечто подобное, но предлагаю 2 уровня генерации; полностью статический (в развертываемую dll), который тогда работает только с общедоступными членами, или в памяти, которая может по-прежнему обращаться к частным членам. Я предполагаю, что они хотели остановиться только на одной модели, что имеет смысл - и им нужен был «sgen», который диктует первую модель.

Частные поля не могут быть сериализованы. Я хотел бы украсить частные поля атрибутом, чтобы XmlSerializer включал их.

Затем используйте DataContractSerializer , который будет сериализовать любой член (включая закрытый), помеченный [DataMember] .

10
ответ дан 5 December 2019 в 05:34
поделиться

См. класс XmlSerializer . Вы увидите, что используете его неправильно. XmlInclude имеет совершенно другое предназначение.

Вы правы. Сериализатор XML существует с .NET 1.0. Это до того, как у нас появились дженерики, кстати, так что вряд ли они поддержат.

Кроме того, с тех пор появились более совершенные технологии:

  • DataContractSerializer работает быстрее и поддерживает двоичную сериализацию
  • LINQ to XML может использоваться во многих сценариях сериализации и является гораздо более гибким

XML-сериализатор вряд ли будет улучшена в будущем. Я рекомендую вам изучить другие альтернативы.

12
ответ дан 5 December 2019 в 05:34
поделиться

1: legacy. XML Serializer предшествует дженерикам. Он появился в .NET 1.0.

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

3: то же, что и 2.

Вы можете использовать сериализатор WCF DataContract по частям.

Ваше предположение "ограниченно неверно". Сериализация XML предположительно предназначена для передачи документов, которые - в моих проектах - всегда являются отдельными классами, не делающими ничего больше. Как таковая, у меня нет проблем со всеми ограничениями.

7
ответ дан 5 December 2019 в 05:34
поделиться

Вам не нужен [XmlInclude] , как будто он у вас есть. Вы можете использовать [XmlElement] [XmlAttribute] ... , чтобы описать способ сериализации класса.

Выньте [XmlInclude] и посмотрите, работает ли это.

class Foo { 
    public Foo (string name) { 
        Name1 = name; 
        Name2 = name; 
    } 

    [XmlAttribute] 
    public string Name1 { get; set; } 

    [XmlAttribute] 
    public string Name2; 
} 

Foo myFoo = new Foo("FirstName", "LastName");
StreamWriter wr = new StreamWriter("path.xml"); 
XmlSerializer serializer = new XmlSerializer(typeof(Foo));
serializer.Serialize(wr,  myFoo);

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

1
ответ дан 5 December 2019 в 05:34
поделиться

Кстати, DataContract никогда не поддерживает двоичную сериализацию, он сериализуется в xml, но поддерживает двоичное кодирование.

0
ответ дан 5 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: