6

例如,我想序列化和反序列化System.Drawing.Font不可变且无法更改以适应 protobuf-net 约定的序列化和反序列化。一般来说,是否可以在 protobuf-net 中编写某种“自定义”序列化程序?

编辑:根据接受的答案,以下是代理的示例System.Drawing

[ProtoContract]
struct ProtoColor
{
    [ProtoMember(1, DataFormat=DataFormat.FixedSize)]
    public uint argb;
    public static implicit operator Color(ProtoColor c) 
        { return Color.FromArgb((int)c.argb); }
    public static implicit operator ProtoColor(Color c)
        { return new ProtoColor { argb = (uint)c.ToArgb() }; }
}
[ProtoContract()]
class ProtoFont
{
    [ProtoMember(1)]
    string FontFamily;
    [ProtoMember(2)]
    float SizeInPoints;
    [ProtoMember(3)]
    FontStyle Style;

    public static implicit operator Font(ProtoFont f) {
        return new Font(f.FontFamily, f.SizeInPoints, f.Style);
    }
    public static implicit operator ProtoFont(Font f) { 
        return f == null ? null : new ProtoFont { 
            FontFamily = f.FontFamily.Name, 
            SizeInPoints = f.SizeInPoints, 
            Style = f.Style };
    }
}
[ProtoContract()]
class ProtoStringFormat
{
    [ProtoMember(1, DataFormat=DataFormat.Group)]
    StringAlignment Alignment;
    [ProtoMember(2)]
    StringAlignment LineAlignment;
    [ProtoMember(3)]
    StringFormatFlags Flags;
    public static implicit operator StringFormat(ProtoStringFormat f) { 
        return new StringFormat(f.Flags) { Alignment = f.Alignment, 
            LineAlignment = f.LineAlignment };
    }
    public static implicit operator ProtoStringFormat(StringFormat f) { 
        return f == null ? null : new ProtoStringFormat() { 
            Flags = f.FormatFlags, Alignment = f.Alignment, 
            LineAlignment = f.LineAlignment };
    }
}

// Before serializing or deserializing...
static RuntimeTypeModel Model;
static StaticConstructor()
{
    Model = TypeModel.Create();
    Model.AllowParseableTypes=true;
    Model.Add(typeof(Color), false).SetSurrogate(typeof(ProtoColor));
    Model.Add(typeof(Font), false).SetSurrogate(typeof(ProtoFont));
    Model.Add(typeof(StringFormat), false)
         .SetSurrogate(typeof(ProtoStringFormat));
    Model.Add(typeof(PointF), true).Add("X", "Y");
}
4

1 回答 1

6

是的。请注意,许多不可变类型将由“自动元组”代码处理 - 如果它有一个构造函数接受看起来就像公共成员的参数,它可以从中推断出行为。

除此之外,您可以编写自己的 DTO,它具有您需要的任何布局/成员,并在自定义 DTO 和目标类型(在本例中为字体)之间添加转换运算符(隐式或显式)。您的操作员将拥有从一个到另一个的代码。然后调用:

 RuntimeTypeModel.Default.Add(typeof(Font), false)
    .SetSurrogate(typeof(YourCustomDTO));

序列化器将使用运算符在两种类型之间进行切换,并使用在线上的自定义 DTO。

注意运算符的传入值是否为空!

于 2013-08-23T16:47:20.603 回答