Color not marked as [Serializable] in 3.2

as the topic says, the Color class is not marked as [Serializable] in MonoGame 3.2, though it certainly was in 3.0.

is there a way to add [Serializable] for this class? (or some other work-around, besides writing custom on-serialize/on-deserialize methods for every single class of mine that has Color fields?)

Serializable was replaced with DataContract.

I covered the limitations of the switch to using [DataContract] in the pull request. They are pretty minimal and likely donā€™t pose any problem for you:

I looked into DataContracts after Nezz posted, and decided it would be easier to write a wrapper struct for Color that IS [Serializable]. writing the wrapper struct was pretty trivial (once I figured out implicit operators to handle assignment from Color to my custom struct). this was pretty easy to do, works, and I canā€™t imagine thereā€™s much CPU overhead involved, so Iā€™m going to stick with it.

thanks for the DataContract pointer, though. I hadnā€™t heard of those, and Iā€™ll definitely look into them for my next project.

You can also use ISerializationSurrogate:

public static class SerializationUtils
{
public static SurrogateSelector MakeSurrogateSelector()
{
var ss = new SurrogateSelector();
ss.AddSurrogate(typeof(Color), new StreamingContext(StreamingContextStates.All), new ColorSerializationSurrogate());
ss.AddSurrogate(typeof(Vector2), new StreamingContext(StreamingContextStates.All), new Vector2SerializationSurrogate());
ss.AddSurrogate(typeof(Vector3), new StreamingContext(StreamingContextStates.All), new Vector3SerializationSurrogate());
ss.AddSurrogate(typeof(Point), new StreamingContext(StreamingContextStates.All), new PointSerializationSurrogate());
ss.AddSurrogate(typeof(Rectangle), new StreamingContext(StreamingContextStates.All), new RectangleSerializationSurrogate());
return ss;
}
}

// This class can manually serialize an Color object.
sealed class ColorSerializationSurrogate : ISerializationSurrogate
{

    // Serialize the Color object
    public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context)
    {
        var col = (Color)obj;
        info.AddValue("r", col.R);
        info.AddValue("g", col.G);
        info.AddValue("b", col.B);
        info.AddValue("a", col.A);         
    }

    // Deserialize the Color object
    public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        var col = (Color)obj;
        col.R = info.GetByte("r");
        col.G = info.GetByte("g");
        col.B = info.GetByte("b");
        col.A = info.GetByte("a");
        return col;
    }
}


sealed class Vector2SerializationSurrogate : ISerializationSurrogate
{
    public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context)
    {
        var vec = (Vector2)obj;
        info.AddValue("x", vec.X);
        info.AddValue("y", vec.Y);
    }

    public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        var vec = (Vector2)obj;
        vec.X = info.GetSingle("x");
        vec.Y = info.GetSingle("y");
        return vec;
    }
}


sealed class Vector3SerializationSurrogate : ISerializationSurrogate
{

    public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context)
    {
        var vec = (Vector3)obj;
        info.AddValue("x", vec.X);
        info.AddValue("y", vec.Y);
        info.AddValue("z", vec.Z);
    }

    public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        var vec = (Vector3)obj;
        vec.X = info.GetSingle("x");
        vec.Y = info.GetSingle("y");
        vec.Z = info.GetSingle("z");
        return vec;
    }
}

sealed class PointSerializationSurrogate : ISerializationSurrogate
{
    public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context)
    {
        var sobj = (Point)obj;
        info.AddValue("x", sobj.X);
        info.AddValue("y", sobj.Y);
    }

    public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        var sobj = (Point)obj;
        sobj.X = info.GetInt32("x");
        sobj.Y = info.GetInt32("y");
        return sobj;
    }
}

sealed class RectangleSerializationSurrogate : ISerializationSurrogate
{
    public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context)
    {
        var sobj = (Rectangle)obj;
        info.AddValue("x", sobj.X);
        info.AddValue("y", sobj.Y);
        info.AddValue("w", sobj.Width);
        info.AddValue("h", sobj.Height);
    }

    public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        var sobj = (Rectangle)obj;
        sobj.X = info.GetInt32("x");
        sobj.Y = info.GetInt32("y");
        sobj.Width = info.GetInt32("w");
        sobj.Height = info.GetInt32("h");
        return sobj;
    }
}
1 Like