如何使用 protobuf-net 序列化封闭的不可变类型? [英] How to serialize a closed immutable type with protobuf-net?

查看:58
本文介绍了如何使用 protobuf-net 序列化封闭的不可变类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,我想对 System.Drawing.Font 进行序列化和反序列化,它是不可变的,不能更改以适应 protobuf-net 约定.一般来说,是否可以在 protobuf-net 中编写某种自定义"序列化程序?

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?

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

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");
}

推荐答案

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

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.

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

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));

序列化器将使用运算符在两种类型之间进行更改,并在线路上使用自定义 DTO.

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

注意运算符的传入值为 null!

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

这篇关于如何使用 protobuf-net 序列化封闭的不可变类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆