没有为类型定义的序列化程序:System.Drawing.Color

时间:2012-06-10 05:09:30

标签: protobuf-net

为了减少网络流量,我想使用protobuf-net而不是BinaryFormatter,但发生了以下错误:

No serializer defined for type: System.Drawing.Color

WBMessage:

[ProtoContract]
[Serializable]
public abstract class WBMessage
{
    [ProtoMember(1)]
    public Color setColor1;

    [ProtoMember(2)]
    public UInt16 userNo;

    public abstract WHITEBOARD_MESSAGE_TYPE MessageType
    {
        get;
    }

    [ProtoMember(3)]
    public string age;

    public enum WHITEBOARD_MESSAGE_TYPE
    {
        enWBBegin,
        enWBLine,
        enWBRectangle,
        enWBRectangleF,
        enWBEllipse,
        enWBEllipseF,
        enWBClearScreen,
        enWBText,
        enWBEnd
    };
}

WBMsgDrawBegin:

[ProtoContract]
[ProtoInclude(1, typeof(WBMessage))]
public class WBMsgDrawBegin : WBMessage
{
    private const WHITEBOARD_MESSAGE_TYPE m_enMsgType =   WHITEBOARD_MESSAGE_TYPE.enWBBegin;
    public override WHITEBOARD_MESSAGE_TYPE MessageType
    {
        get
        {
            return m_enMsgType;
        }
    }

    [ProtoMember(4)]
    public int x;

    [ProtoMember(5)]
    public int y;

    [ProtoMember(6)]
    public bool m_bMouseDown;

    [ProtoMember(7)]
    public string name;
}

用法:

WBMsgDrawBegin item1 = new WBMsgDrawBegin();
item1.setColor1 = Color.AliceBlue;
item1.name = "test";
item1.age = "31";

item1.x = 10998;
item1.y = 10089;

Stream stream = new MemoryStream();
MemoryStream ms = new MemoryStream();
Serializer.SerializeWithLengthPrefix<WBMsgDrawBegin>(ms, item1, PrefixStyle.Base128, 0);

3 个答案:

答案 0 :(得分:4)

它不保证能够处理所有平台都不支持的所有已知BCL类型,特别是图形库之类的东西。我建议:

public Color Foo {get;set;}

[ProtoMember(n, DataFormat=DataFormat.Fixed)]
private int FooSerialized {
    get { return Foo.ToArgb(); }
    set { Foo = Color.FromArgb(value); }
}

将序列化为固定的4字节块。如果你有很多颜色属性,你也可以使用“代理”来做一些非常相似的事情(代码少,但每个项目额外增加2个字节)。

答案 1 :(得分:2)

那么问题是什么?

内置颜色类没有序列化器。

如果你想通过线路传递颜色,你将不得不以其他方式表达,例如为ARGB发送一个32位整数,这是很常见的颜色。

有许多标准的颜色交流方式。我建议你坚持这样做的标准方式,而不是试图定义自己的方式。只需坚持使用32位整数或4字节ARGB。

答案 2 :(得分:1)

由于我整个早上都在尝试类似的东西,我会补充一点,存储Point,Size,Rectangle和Color等的另一种方法是使用NET的内置转换器。代码是在VB中,但你应该得到足够好的漂移:

Imports System.Drawing
Imports System.ComponentModel

Private Function GetInvariantString(ByVal v As Object) As String
    Dim conv As TypeConverter = TypeDescriptor.GetConverter(v.GetType)
    Dim t As System.Type = v.GetType

    ' at least in VB '=' and 'Is' are not defined for Boolean 
    '  and System.Type so I cant find a way to word the Case 
    '  test so, it's inverted...only one Case can be true anyway
    Select Case True
        ...
        Case t Is GetType(Drawing.Point)
            Return conv.ConvertToInvariantString(v)

        Case t Is GetType(Drawing.Size)
            Return conv.ConvertToInvariantString(v)

        Case t Is GetType(Drawing.Color)
            Return conv.ConvertToInvariantString(v)

        Case Else
            Throw New ArgumentException("Unknown Type " & v.type.ToString)
    End Select

End Function

myPoint.ToString的简单方法将返回{X=11 Y=156}之类的内容,但对于此处处理的类型,并不总是有一个互补的FromString方法。 ConvertToInvariantString返回11, 156并可用于重建Point(以及其余部分):

Private Function TypeFromInvariantString(ByVal pbnString As String,  _
            ByVal ttype As Type) As Object

    ' same thing...
    Select Case True
        Case ttype Is GetType(Point)
            Return TypeDescriptor.GetConverter(GetType(Drawing.Point)).ConvertFromInvariantString(pbnString)

        Case ttype Is GetType(Size)
            Return TypeDescriptor.GetConverter(GetType(Drawing.Size)).ConvertFromInvariantString(pbnString)

        Case ttype Is GetType(Color)
            Return TypeDescriptor.GetConverter(GetType(Drawing.Color)).ConvertFromInvariantString(pbnString)

        Case Else
            Throw New ArgumentException("Unknown Type " & ttype.ToString)
    End Select


End Function

矩形,SizeF等(甚至字体)都可以以相同的方式处理。就个人而言,对于Color我更喜欢存储/传递表示ARGB值的Int,但是Invariant字符串方法效果也很好,如果颜色是像“Red”这样的命名颜色,那么Red就是全部返回/序列化。用法:

' serializer version
<ProtoMember(6)> _
Private Property PBNImgPoint() As String
    Get
        Return GetInvariantString(_ImgPoint)
    End Get
    Set(ByVal value As String)
        _ImgPoint = TypeFromInvariantString(value, GetType(Point))
    End Set
End Property

' method used in code/program....
Friend Property ImgPoint() As Point
    Set(ByVal value As Point)
        _ImgPoint = value
    End Set
    Get
        Return _ImgPoint
    End Get
End Property

显然,转换可能发生在每个Getter / Setter而不是被调用的过程中,但我的pilot / test case有多个Points,Rectangles和Sizes,我想确保它们都被处理完毕。

HTH