Самая элегантная XML-сериализация цветовой структуры

Одна проблема прослушивала меня достаточно, чтобы зарегистрироваться в Stack Overflow. В настоящее время, если я хочу сериализовать строку «Цвет в XML» с именем color или #rrggbb или #aarrggbb , я делаю это следующим образом:

 [XmlIgnore()] public Color color; [XmlElement(ElementName = "Color")] public String color_XmlSurrogate { get { return MyColorConverter.SetColor(color); } set { color = MyColorConverter.GetColor(value); } } 

Здесь MyColorConverter делает сериализацию именно так, как мне нравится. Но все это похоже на клод, с дополнительным полем и всем. Есть ли способ заставить его работать в меньших количествах, возможно, подключая TypeDescriptor с атрибутами C #, связанными с XML?

Вот что я использую для сериализации структуры Color в XML. Это лучше, чем, по-моему, затенение основного свойства Color . Любые предложения приветствуются.

Класс XmlColor основывается главным образом на implicit operator функции языка implicit operator обеспечивающей основные преобразования данных. Без этого class в основном бесполезен. Были добавлены другие функциональные возможности для округления classа.

XmlColor также обеспечивает удобный способ разделения цветовых компонентов. Я добавил свойство Alpha чтобы показать это. Обратите внимание на то, что компонент Alpha не будет сериализован, если он коленчатый до 255.

Дезертировка значения цвета в Web объединяет значение Alpha настоящее время хранится в экземпляре. Порядок, в котором анализируются атрибуты, не имеет значения. Если в источнике XML отсутствует атрибут Alpha значение компонента экземпляра будет использоваться для установки уровня Alpha . Это, возможно, ошибочно; однако в случае сериализации XML class XmlColor будет инициализирован с помощью Color.Black значение Alpha для 255.

Я работаю над средой VS2010 и строю против .NET 4. Я понятия не имею, насколько совместим код с предыдущими версиями.

Вот пример свойства, которое должно быть сериализовано в XML:

  [XmlElement(Type=typeof(XmlColor))] public Color MyColor { get; set; } 

Вот хелпер-class XmlColor :

 public class XmlColor { private Color color_ = Color.Black; public XmlColor() {} public XmlColor(Color c) { color_ = c; } public Color ToColor() { return color_; } public void FromColor(Color c) { color_ = c; } public static implicit operator Color(XmlColor x) { return x.ToColor(); } public static implicit operator XmlColor(Color c) { return new XmlColor(c); } [XmlAttribute] public string Web { get { return ColorTranslator.ToHtml(color_); } set { try { if (Alpha == 0xFF) // preserve named color value if possible color_ = ColorTranslator.FromHtml(value); else color_ = Color.FromArgb(Alpha, ColorTranslator.FromHtml(value)); } catch(Exception) { color_ = Color.Black; } } } [XmlAttribute] public byte Alpha { get { return color_.A; } set { if (value != color_.A) // avoid hammering named color if no alpha change color_ = Color.FromArgb(value, color_); } } public bool ShouldSerializeAlpha() { return Alpha < 0xFF; } } 

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

 [XmlIgnore] public Color BackColor { get; set; } [XmlElement("BackColor")] public int BackColorAsArgb { get { return BackColor.ToArgb(); } set { BackColor = Color.FromArgb(value); } } 

Боль, не так ли? Это все, что вы можете сделать с XmlSerializer , если вы не реализуете IXmlSerializable (который я не рекомендую). Опции:

  • придерживайтесь этого, но также color_XmlSurrogate как [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] – это остановит его появление в большинстве представлений привязки данных и в редакторе кода при ссылке на вашу сборку в виде dll
  • используйте DataContractSerializer , который поддерживает частные свойства (но который не поддерживает атрибуты xml, вы не можете выиграть …)

Кстати, у меня был бы color как свойство, а не поле:

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

Поскольку это мой первый вопрос, я решил изучить его больше. @bvj дал отличный ответ. Я изменил его код, так что вот оно. Класс XmlColor изменяется так, что сериализованная строка идет в тексте тега, и существуют публичные статические функции, если строка должна быть сериализована как атрибут XML вместо тега. Атрибуты, к сожалению, все же должны быть сериализованы с суррогатными полями, но, пожалуйста, исправьте меня, если я ошибаюсь. Использование classа:

 // Color as tag [XmlElement(Type = typeof(XmlColor))] public Color ColorAsTag { get; set; } // Color as attribute [XmlIgnore] public Color ColorAsAttribute { get; set; } [XmlAttribute("ColorAsAttribute")] public string ColorAsAttribute_XmlSurrogate { get { return XmlColor.FromColor(ColorAsAttribute); } set { ColorAsAttribute = XmlColor.ToColor(value); } } 

Класс, который делает это:

 public class XmlColor { private Color color_ = Color.Black; public XmlColor() { } public XmlColor(Color c) { color_ = c; } public static implicit operator Color(XmlColor x) { return x.color_; } public static implicit operator XmlColor(Color c) { return new XmlColor(c); } public static string FromColor(Color color) { if (color.IsNamedColor) return color.Name; int colorValue = color.ToArgb(); if (((uint)colorValue >> 24) == 0xFF) return String.Format("#{0:X6}", colorValue & 0x00FFFFFF); else return String.Format("#{0:X8}", colorValue); } public static Color ToColor(string value) { try { if (value[0] == '#') { return Color.FromArgb((value.Length <= 7 ? unchecked((int)0xFF000000) : 0) + Int32.Parse(value.Substring(1), System.Globalization.NumberStyles.HexNumber)); } else { return Color.FromName(value); } } catch (Exception) { } return Color.Black; } [XmlText] public string Default { get { return FromColor(color_); } set { color_ = ToColor(value); } } } 

Я нашел другое решение,

Вместо System.Drawing.Color можно использовать System.Windows.Media.Color .
Это сериализуемо для XML.

  • .NET XML-сериализация gotchas?
  • Лучшее решение для XmlSerializer и System.Drawing.Color
  • Использование XmlSerializer для сериализации производных classов
  • XmlSerializer: удалить ненужные пространства имен xsi и xsd
  • Сериализация списка пар ключ / значение в XML
  • Сериализация Xml - Скрыть нулевые значения
  • Как добавить атрибут XmlInclude динамически
  • Исключение некоторых свойств во время сериализации без изменения исходного classа
  • Сериализация объекта в XML
  • Проверка того, является ли объект числом в C #
  • Почему в .NET нет XML-сериализуемого словаря?
  • Interesting Posts

    Каков любопытно повторяющийся шаблон шаблона (CRTP)?

    Заключительные стоп-сигналы от бодрствования Windows 10 desktop

    Окончательный способ запуска событий нажатия клавиш с помощью jQuery

    абсолютная и относительная ширина и высота положения

    Преобразование short в байт в Java

    Почему вывод 0000 и как?

    Как можно хранить данные в CMOS?

    Быстрый способ преобразования двумерного массива в список (одномерный)

    iPhone XMLRequest

    SD-карта сжимается в допустимом размере после копирования образа диска

    Что такое / usr / bin / [и как его использовать?

    Указанное именованное соединение либо не находится в конфигурации, не предназначено для использования с поставщиком EntityClient, либо недействительно

    Можем ли мы передать модель в качестве параметра в RedirectToAction?

    Android: добавление статического заголовка в начало ListActivity

    Как добавить пользовательскую вкладку Ribbon с помощью VBA?

    Давайте будем гением компьютера.