В моей музыке / ритм-игре я использовал сериализацию для сохранения созданных пользователем simfiles (например, музыкальных вкладок или блокнотов). Ничего особенного там нет. Но я использую DataContract для выполнения сериализации, потому что:
1) Мне также нужно сериализовать приватные и защищенные поля. Мне все равно, если они видны, в основном из-за ...
2) Я бы хотел, чтобы пользователь мог редактировать сериализованный файл в своем любимом текстовом редакторе и загружать их в игру (эти файлы будут использоваться для представления музыкальных нот в игре, подумайте * 1004). * StepMania simfiles ).
Один из моих пользовательских типов данных, которые я хотел бы сериализовать, - это созданный мной класс Fraction:
using System.Runtime.Serialization;
namespace Fractions {
[DataContract(Namespace="")] // Don't need the namespaces.
public sealed class Fraction {
// NOTE THAT THESE ARE "READONLY"!
[DataMember(Name="Num", Order=1)] private readonly long numer;
[DataMember(Name="Den", Order=2)] private readonly long denom;
// ...LOTS OF STUFF...
public static Fraction FromString(string str) {
// Try and parse string and create a Fraction from it, and return it.
// This is static because I'm returning a new created Fraction.
}
public override ToString() {
return numer.ToString() + "/" + denom.ToString();
}
}
}
Тестируя это, он работает прилично, сериализуя в XML-фрагмент вида:
<Fraction>
<Num>(INT64 VALUE AS STRING)</Num>
<Den>(INT64 VALUE AS STRING)</Den>
</Fraction>
Теперь, я мог бы быть счастлив с этим и продолжать свой веселый путь кодирования. Но я придирчив.
Мои конечные пользователи, вероятно, не будут в совершенстве знакомы с XML, и в моей игре МНОГО более сложных типов данных, которые будут включать много фракций, поэтому я бы предпочел иметь возможность представлять фракцию в XML-файл как таковой (гораздо более краткий):
<Fraction>(NUMERATOR)/(DENOMINATOR)</Fraction>
Однако я не знаю, как это сделать, не прерывая автоматическую (де) сериализацию. Я заглянул в интерфейс IXmlSerializable
, но меня закрыл тот факт, что мой тип данных должен быть изменяемым, чтобы он работал (ReadXml () не возвращает новый объект Fraction, но вместо этого, кажется, выполняет flash-экземпляр один, и вы должны заполнить значения вручную, что не работает из-за readonly
). Использование атрибутов OnSerializing и OnDeserialized также не работало по той же причине. Я ДЕЙСТВИТЕЛЬНО предпочел бы, чтобы мой класс фракций оставался неизменным.
Я предполагаю, что есть стандартная процедура, с помощью которой при сериализации в XML примитивы преобразуются в / из строк. Любые числовые примитивы, например, должны быть преобразованы в / из строк при сериализации / десериализации. Есть ли способ для меня, чтобы иметь возможность добавить этот вид автоматической строки из / в преобразование в мой тип фракции? Если бы это было возможно, я бы подумал, что процедура сериализации будет выглядеть примерно так:
1) Сериализуйте этот сложный тип данных, который содержит поля Fraction.
2) Начать сериализацию полей [DataMember].
3) Эй, это поле является дробным объектом. Фракции могут полностью представить себя в виде строки. Запишите эту строку непосредственно в XML, вместо того, чтобы погрузиться в объект Fraction и записать все его поля.
...
Десериализация будет работать наоборот:
1) Десериализовать эти данные, мы ожидаем такой-то тип данных.
2) Запустите десериализацию полей.
3) О, смотри, объект Fraction, я могу просто прочитать строку содержимого, преобразовать эту строку в новый объект Fraction и вернуть только что созданную Fraction.
...
Могу ли я что-нибудь сделать для этого? Спасибо!
РЕДАКТИРОВАТЬ: Суррогаты контрактов данных, похоже, путь, но я не могу понять их или заставить их работать в моей игре. Или, скорее, они добавляют некоторые неприятные автоматические поля имен и идентификаторов к моим сериализованным элементам.