Я воображаю для использования сериализации 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 на самом деле предлагает описанные возможности? Там чередуйтесь, сериализаторы к XML, которые обрабатывают эти случаи более сложно?
Если нет: мы в 2010, в конце концов, и.NET была вокруг много лет. Сериализация XML часто используется, полностью стандартная и должна быть действительно легкой работать. Или мое понимание возможно неправильно, и сериализация XML не должна выставлять описанные функции серьезного основания?
Править: Наследие не является серьезным основанием imo. List
было неуниверсально сначала, также.
(Не стесняйтесь корректировать подпись или теги. Если это должно быть CW, просто напишите.)
Сначала фиксированный код, затем ответы на ваши вопросы:
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]
.
См. класс XmlSerializer . Вы увидите, что используете его неправильно. XmlInclude
имеет совершенно другое предназначение.
Вы правы. Сериализатор XML существует с .NET 1.0. Это до того, как у нас появились дженерики, кстати, так что вряд ли они поддержат.
Кроме того, с тех пор появились более совершенные технологии:
XML-сериализатор вряд ли будет улучшена в будущем. Я рекомендую вам изучить другие альтернативы.
1: legacy. XML Serializer предшествует дженерикам. Он появился в .NET 1.0.
2: проектное решение. Сериализатор XML должен работать с очень ограниченными правами, по сравнению с другими решениями.
3: то же, что и 2.
Вы можете использовать сериализатор WCF DataContract по частям.
Ваше предположение "ограниченно неверно". Сериализация XML предположительно предназначена для передачи документов, которые - в моих проектах - всегда являются отдельными классами, не делающими ничего больше. Как таковая, у меня нет проблем со всеми ограничениями.
Вам не нужен [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);
Обновлено, сериализованные свойства должны быть общедоступными.
Кстати, DataContract никогда не поддерживает двоичную сериализацию, он сериализуется в xml, но поддерживает двоичное кодирование.