【问题标题】:How to XmlSerialize System.Drawing.Font class如何 XmlSerialize System.Drawing.Font 类
【发布时间】:2010-12-28 17:57:36
【问题描述】:

System.Drawing.Font 不是 XML 可序列化的,因为它没有默认(空)构造函数。
尽管如此,是否有一些解决方法或替代方法来序列化Font

【问题讨论】:

    标签: c# .net serialization


    【解决方案1】:

    MSDN page for the Font class 上给出了有关如何通过实现可序列化的包装类来做到这一点的建议。

    【讨论】:

    • 是的 - 真正 xml 可序列化的类的包装器是恕我直言的方法
    【解决方案2】:

    编辑:我根据Regent 的建议更新了代码以使用FontConverter,同时保留了将SerializableFont 用作常规Font 的能力。

    public class SerializableFont
    {
        public SerializableFont()
        {
            FontValue = null;
        }
    
        public SerializableFont(Font font)
        {
            FontValue = font;
        }
    
        [XmlIgnore]
        public Font FontValue { get; set; }
    
        [XmlElement("FontValue")]
        public string SerializeFontAttribute
        {
            get
            {
                return FontXmlConverter.ConvertToString(FontValue);
            }
            set
            {
                FontValue = FontXmlConverter.ConvertToFont(value);
            }
        }
    
        public static implicit operator Font(SerializableFont serializeableFont)
        {
            if (serializeableFont == null )
                return null;
            return serializeableFont.FontValue;
        }
    
        public static implicit operator SerializableFont(Font font)
        {
            return new SerializableFont(font);
        }
    }
    
    public static class FontXmlConverter
    {
        public static string ConvertToString(Font font)
        {
            try
            {
                if (font != null)
                {
                    TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font));
                    return converter.ConvertToString(font);
                }
                else 
                    return null;
            }
            catch { System.Diagnostics.Debug.WriteLine("Unable to convert"); }
            return null;
        }
        public static Font ConvertToFont(string fontString)
        {
            try
            {
                TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font));
                return (Font)converter.ConvertFromString(fontString);
            }
            catch { System.Diagnostics.Debug.WriteLine("Unable to convert"); }
            return null;
        }
    }
    

    用法:当您拥有Font 属性时,将其声明为SerializableFont。这将允许它被序列化,而隐式转换将为您处理转换。

    而不是写:

    Font MyFont {get;set;}
    

    写:

    SerializableFont MyFont {get;set;}
    

    【讨论】:

    • 严格来说,您最终得到了一些 xml,但实际上您已经消除了 xml 的所有语义丰富性,只需将其二进制内容转储到 base64 编码的文本元素中。恕我直言,从这个词的有用意义来看,这真的不是“xml 序列化”。这不像您可以“看到” xml 中的任何 Font 属性,而无需先反序列化,您也不能对其进行 XPath、转换、迭代等
    【解决方案3】:

    试试 DataContractSerializer。

            Font fnt = new Font("Arial", 1);
            MemoryStream data = new MemoryStream();
            DataContractSerializer dcs = new DataContractSerializer(typeof(Font), new[] { typeof(FontStyle), typeof(GraphicsUnit) });
            dcs.WriteObject(data, fnt);
            string xml = Encoding.UTF8.GetString(data.ToArray());
    

    【讨论】:

      【解决方案4】:

      System.Drawing.Font 有一个关联的FontConverter 类,我会手动转换它:

      [Serializable]
      public class SerializableFont
      {
          public SerializableFont()
          {
              this.Font = null;
          }
      
          public SerializableFont(Font font)
          {
              this.Font = font;
          }
      
          [XmlIgnore]
          public Font Font { get; set; }
      
          [XmlElement("Font")]
          public string FontString
          {
              get
              {
                  if (font != null)
                  {
                      TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font));
      
                      return converter.ConvertToString(this.Font);
                  }
                  else return null;
              }
              set
              {
                  TypeConverter converter = TypeDescriptor.GetConverter(typeof(Font));
      
                  this.Font = converter.ConvertFromString(value);
              }
          }
      }
      

      【讨论】:

      • 这个解决方案对我有用,谢谢!虽然很想知道为什么不直接使用FontConverter converter = new FontConverter(); 或者这样可以吗?
      • 刚刚在MSDN 上发现了这个:它说通过调用GetConverter 方法通过TypeDescriptor 类访问FontConverter 类。但仍然不知道为什么。
      • @Ben,我认为这可能有几个原因,首先TypeDescriptor 可能已经创建了FontConverter 的实例,所以你不需要每次都浪费内存创建一个;其次,他们可能希望在框架的未来版本中将 FontConverter 替换为其他内容,而使用 TypeDescriptor 在这方面提供了更大的灵活性。
      【解决方案5】:

      我使用可序列化的字体,与Elad's 略有不同。

      在我的可序列化数据实体中,我隐藏 ([XmlIgnore]) 具有 Font 类型的属性并公开具有 SerializableFont 类型的属性,它被序列化程序“吃掉”。

      请注意,这仅适用于XmlSerializer

      /// <summary>
      /// Font descriptor, that can be xml-serialized
      /// </summary>
      public class SerializableFont
      {
          public string FontFamily { get; set; }
          public GraphicsUnit GraphicsUnit { get; set; }
          public float Size { get; set; }
          public FontStyle Style { get; set; }
      
          /// <summary>
          /// Intended for xml serialization purposes only
          /// </summary>
          private SerializableFont() { }
      
          public SerializableFont(Font f)
          {
              FontFamily = f.FontFamily.Name;
              GraphicsUnit = f.Unit;
              Size = f.Size;
              Style = f.Style;
          }
      
          public static SerializableFont FromFont(Font f)
          {
              return new SerializableFont(f);
          }
      
          public Font ToFont()
          {
              return new Font(FontFamily, Size, Style,
                  GraphicsUnit);
          }
      }
      

      【讨论】:

        【解决方案6】:

        它过于复杂,仍然不适用于 PropertyGrid。这是简单易行的解决方案。

        首先将以下2个方法放入类中。

        protected static string FontToString(Font font)
        {
            try
            {
                if (font == null)
                    return null;
        
                var converter = TypeDescriptor.GetConverter(typeof(Font));
                return converter.ConvertToString(font);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.ToString());
            }
            return null;
        }
        
        protected static Font StringToFont(string text)
        {
            try
            {
                var converter = TypeDescriptor.GetConverter(typeof(Font));
                return (Font)converter.ConvertFromString(text);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.ToString());
            }
            return null;
        }
        

        然后添加属性。

        [Category("General")]
        [XmlIgnore]
        public Font LogFont
        {
            get
            {
                return StringToFont(LogFontValue);
            }
            set
            {
                LogFontValue = FontToString(value);
            }
        }
        
        [Browsable(false)]
        public string LogFontValue { get; set; } = "Lucida Console, 12pt";
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多