How to serialize a closed immutable type with protobuf-net?

拈花ヽ惹草 提交于 2019-12-17 20:38:39

问题


For example, I would like to serialize and deserialize System.Drawing.Font which is immutable and cannot be altered to suit protobuf-net conventions. In general, is it possible to write some sort of "custom" serializer in protobuf-net?

Edit: Based on the accepted answer, here are examples of proxies for 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");
}

回答1:


Yes. Note that many immutable types will be handled by the "auto tuple" code - if it has a constructor that accepts parameters that look just like the public members, it can infer the behaviour from that.

Other than that, you can write your own DTO that has whatever layout / members you need, and add conversion operators (implicit or explicit) to and from your custom DTO and the target type (Font in this case). Your operator would have the code to get from one to the other. Then call:

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

The serializer will use the operators to change between the two types, and use the custom DTO on the wire.

Watch out for the incoming value to the operator being null!



来源:https://stackoverflow.com/questions/18405160/how-to-serialize-a-closed-immutable-type-with-protobuf-net

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!