为了减少网络流量,我想使用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);
答案 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