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

Protobuf net 没有为类型定义序列化程序:System.Drawing.Color,protobuf-net,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

为了减少网络流量,我想使用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
    };
}
[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);
WBMsgDrawBegin:

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

[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
    };
}
[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);
WBMsgDrawBegin item1=新的WBMsgDrawBegin();
item1.setColor1=Color.AliceBlue;
item1.name=“测试”;
项目1.age=“31”;
项目1.x=10998;
第1项y=10089;
Stream=新的MemoryStream();
MemoryStream ms=新的MemoryStream();
Serializer.SerializeWithLengthPrefix(ms,item1,PrefixStyle.Base128,0);

那么问题是什么

内置颜色类没有序列化程序

如果您想通过有线传输颜色,则必须使用其他表示方式,例如为ARGB发送32位整数,这是颜色的常见做法


有许多传达颜色的标准方式。不过,我建议你坚持一种标准的方式,而不是试图定义自己的方式。只需使用32位整数或4字节ARGB即可。

它不能保证处理所有已知的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个字节)。

因为我整个上午都在努力做类似的事情,我要补充的是,另一种存储点、大小、矩形和颜色等的方法是使用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
返回
11156
,可用于重建点(以及其他点):

矩形、SizeF等(甚至字体)都可以用相同的方式处理。就个人而言,对于
Color
而言,我更喜欢存储/传递表示ARGB值的Int,但是不变字符串方法也可以很好地工作,如果颜色是一种命名颜色,比如“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
序列化程序版本 _ 私有属性PBNImgPoint()作为字符串 得到 返回GetInvariantString(_ImgPoint) 结束 设置(ByVal值作为字符串) _ImgPoint=TypeFromInvariantString(值,GetType(点)) 端集 端属性 '代码/程序中使用的方法。。。。 友元属性ImgPoint()作为点 设置(ByVal值作为点) _ImgPoint=值 端集 得到 返回点 结束 端属性 显然,转换可以在每个Getter/Setter中进行,而不是在一个被调用的过程中进行,但是我的试验/测试用例有多个点、矩形和大小,我想确保它们都得到了相同的处理


HTH

你能把WBMessage类定义的其余部分包括进来吗?马克,谢谢你的回答,我的问题已经解决了。还有一个问题,你能告诉我如何序列化点的数据类型。@Hudson点的确切类型是什么?有几个,来自不同的框架现在我正在用visual c开发一个项目,框架的版本是V3.5。这个解决方案要求每个要序列化的
颜色
值都有一个单独的属性。“代理”似乎是一个更好的解决方案,尽管我不认为这允许您将颜色存储为原始整数(即代理具有更高的开销,并且与上述解决方案不兼容):谢谢您的回答。我是.Net开发的新手,所以始终使用默认数据类型,例如颜色,我使用System.drawing.color类,point我使用System.drawing.point类。现在根据你的建议,颜色问题已经解决了。