代码之家  ›  专栏  ›  技术社区  ›  Dialecticus

最优雅的颜色结构XML序列化

  •  35
  • Dialecticus  · 技术社区  · 15 年前

    有一个问题困扰了我,使我无法注册堆栈溢出。当前,如果要将颜色序列化为XML字符串作为命名颜色,或 #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和与XML相关的C属性连接起来?

    6 回复  |  直到 7 年前
        1
  •  65
  •   bvj    15 年前

    下面是我用来序列化 Color XML中的结构。总比跟踪初选好 我认为是财产。欢迎提出任何建议。

    这个 XmlColor implicit operator 提供关键数据转换的语言特性。没有这个,这个班基本上就没用了。其他一些功能被添加到类中。

    这个 XML颜色 Alpha 属性来显示此。注意 如果组件一直启动到255,它就不会被序列化。

    反序列化 Web 颜色值组合 阿尔法 当前存储在实例中的值。属性的解析顺序应该无关紧要。如果 阿尔法 属性,实例组件值将用于设置 阿尔法 水平。这可以说是错误的;但是,在XML序列化的情况下 XML颜色 类将初始化为 Color.Black 阿尔法 到255。

    我正在VS2010环境中工作,并根据.NET4进行构建。我不知道代码与以前的版本有多兼容。

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

    这是你的答案 XML颜色 助手类:

    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; }
    }
    
        2
  •  22
  •   Niall C.    13 年前

    [XmlIgnore]
    public Color BackColor { get; set; }
    
    [XmlElement("BackColor")]
    public int BackColorAsArgb
    {
        get { return BackColor.ToArgb();  }
        set { BackColor = Color.FromArgb(value); }
    }
    
        3
  •  5
  •   Marc Gravell    15 年前

    很痛,不是吗?这就是你能做的 XmlSerializer IXmlSerializable (我就是这么做的 推荐)。选项:

    • 坚持住,还有马克 color_XmlSurrogate 作为 [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    • 使用 DataContractSerializer ,它支持私有属性(但 支持xml属性;你赢不了……)

    顺便说一句,我想 color 作为属性而不是字段:

    [XmlIgnore]
    public Color Color {get;set;}
    
        4
  •  4
  •   Dialecticus    14 年前

    XmlColor 类进行更改,以便序列化的字符串进入标记的文本中,并且如果字符串应该序列化为XML属性而不是标记,则存在公共静态函数。不幸的是,属性仍然必须用代理项字段序列化,但是如果我错了,请纠正我。使用类:

    // 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); }
        }
    }
    
        5
  •  2
  •   Andrey Rubshtein    14 年前

    可以使用 System.Windows.Media.Color 系统图颜色 .
    它可以序列化为XML。

        6
  •  0
  •   Jonathan Lidbeck    7 年前

    对于那些使用 System.Windows.Media.Color ,@bvj的解决方案可以简化,利用类的 ToString 方法:

        using System.Windows.Media;
    
        public class XmlColor
        {
            private Color m_color;
    
            public XmlColor() { }
            public XmlColor(Color c) { m_color = c; }
    
            public static implicit operator Color(XmlColor x)
            {
                return x.m_color;
            }
    
            public static implicit operator XmlColor(Color c)
            {
                return new XmlColor(c);
            }
    
            [XmlText]
            public string Default
            {
                get { return m_color.ToString(); }
                set { m_color = (Color)ColorConverter.ConvertFromString(value); }
            }
        }
    }
    

    [XmlElement(Type = typeof(XmlColor))]

    默认情况下, System.Media.Color

    <DisplayColor>
      <A>255</A>
      <R>123</R>
      <G>0</G>
      <B>0</B>
      <ScA>1</ScA>
      <ScR>0.482352942</ScR>
      <ScG>0</ScG>
      <ScB>0</ScB>
    </DisplayColor>
    

    通过上述转换,它将序列化为:

    <DisplayColor>#FF7B0000</DisplayColor>