开发者

How to XmlSerialize System.Drawing.Font class

The classSystem.Drawing.Font is not XML Serializable since it doesn't have a default (empty) constructor.

Is there some work around or alternative wa开发者_StackOverflow社区y to serialize Font nevertheless?


Edit: I updated the code according to Regent suggestion to use FontConverter, while preserving the ability to use the SerializableFont as regular 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;
    }
}

Usage: When you have a Font property, declare it as SerializableFont. This will allow it to be serialized, while the implicit cast will handle the conversion for you.

Instead of writing:

Font MyFont {get;set;}

Write:

SerializableFont MyFont {get;set;}


I use a serializable font, somewhat different from Elad's.

In my serializable data-entities I hide ([XmlIgnore]) the property with the Font type and expose the property with the SerializableFont type, which is "eaten" by the serializer.

Note that this is applicable to the XmlSerializer only.

/// <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);
    }
}


A suggestion on how to do this by implementing a wrapper class that is serializable is given on the MSDN page for the Font class.


System.Drawing.Font have an associated FontConverter class and I would manually converting it:

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


Try the 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());


It is overly complicated and still doesn't work with PropertyGrid. Here is the simple and easy solution.

First put following 2 methods in the class.

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;
}

Then add properties.

[Category("General")]
[XmlIgnore]
public Font LogFont
{
    get
    {
        return StringToFont(LogFontValue);
    }
    set
    {
        LogFontValue = FontToString(value);
    }
}

[Browsable(false)]
public string LogFontValue { get; set; } = "Lucida Console, 12pt";
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜