2009-12-21 11 views

risposta

19

Edit: ho aggiornato il codice secondo Regent suggerimento di utilizzare FontConverter, pur mantenendo la possibilità di utilizzare il SerializableFont come regolare 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; 
    } 
} 

Utilizzo: Quando si dispone di una proprietà Font, dichiareremo come SerializableFont. Ciò consentirà di essere serializzato, mentre il cast implicito gestirà la conversione per te.

Invece di scrivere:

Font MyFont {get;set;} 

scrittura:

SerializableFont MyFont {get;set;} 
+6

In senso stretto si è finito con un po 'di XML, ma in realtà hai eliminato tutta la ricchezza semantica del linguaggio XML da solo scaricare i suoi contenuti binari in un elemento di testo con codifica Base64. IMHO In realtà non è "serializzato xml" nel senso pratico della parola. Non è possibile "vedere" nessuna delle proprietà Font nel xml, senza prima deserializzare, né XPath, trasformarlo, scorrere su di esso, ecc. –

4

Un suggerimento su come eseguire questa operazione implementando una classe wrapper che è serializzabile è fornito su MSDN page for the Font class.

+1

Sì - un wrapper per la classe che è XML genuinamente serializzabile è la strada da percorrere IMHO –

1

provare il 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()); 
2

System.Drawing.Font hanno un associato FontConverter classe e lo manualmente convertendolo:

[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); 
     } 
    } 
} 
+0

Questa soluzione ha funzionato per me, grazie! Sebbene sia interessato a sapere perché non usare solo 'FontConverter converter = new FontConverter();' o è ok? – Ben

+0

L'ho trovato su [MSDN] (http://msdn.microsoft.com/en-us/library/system.drawing.fontconverter.aspx): Dice _Accedi alla classe FontConverter tramite la classe TypeDescriptor chiamando il metodo GetConverter_. Ma ancora non sono sicuro del perché. – Ben

+0

@Ben, ritengo che potrebbero esserci diversi motivi per questo, in primo luogo 'TypeDescriptor' potrebbe aver già creato un'istanza di' FontConverter', quindi non è necessario sprecare memoria creando uno ogni volta; in secondo luogo, potrebbero voler sostituire 'FontConverter' con qualcos'altro nelle future versioni del Framework e usare' TypeDescriptor' per maggiore flessibilità. – Regent

4

Utilizzo un carattere serializzabile, alquanto differente da Elad's.

Nei miei serializzabili data-entità I nascondere ([XmlIgnore]) la proprietà con il tipo Font ed esporre la proprietà con il tipo SerializableFont, che viene "mangiata" dal serializzatore.

Si noti che questo è applicabile solo a 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); 
    } 
}