1

我需要将其添加System.Drawing.Color到默认模型,但它的值是只读的,所以我尝试执行以下操作:

MetaType colorMeta = RuntimeTypeModel.Default.Add(typeof(Color), true);

MethodInfo methodInfo = typeof(Color).GetMethod("FromArgb", new Type[] { typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32) });

colorMeta.AddField(1, "A");
colorMeta.AddField(2, "R");
colorMeta.AddField(3, "G");
colorMeta.AddField(4, "B");

colorMeta.SetFactory(methodInfo);

我得到:

InvalidOperationException : Operation is not valid due to the current state of the object
4

1 回答 1

1

那里有几个问题;首先,在这种情况下,“工厂”需要是创建类型实例的静态方法,但它不会值执行此操作 - 它不打算与FromArgb.

其次,protobuf - net 无法对 /// 属性做很多事情,A因为R它们缺少 setter。GB

不过,您的想法有其优点——这与现有的自动元组功能非常相似——主要区别在于自动元组代码希望有一个与所有明显成员匹配的构造函数。Color没有这样的构造函数,但也许值得我看看是否可以扩展元组代码以允许工厂方法而不仅仅是构造函数。

但是,目前(不更改任何代码)可能有两个可行的选择:

  • 告诉模型序列化私有字段,并跳过构造函数
  • 使用代理

我可能会建议后者更容易。例如,以下工作(使用固定的 4 字节布局,因为这应该适用于所有颜色):

using ProtoBuf;
using ProtoBuf.Meta;
using System.Drawing;

[ProtoContract]
struct ColorSurrogate
{
    public int Value { get { return value; } }
    [ProtoMember(1, DataFormat = DataFormat.FixedSize)]
    private int value;
    public ColorSurrogate(int value) { this.value = value; }

    public static explicit operator Color(ColorSurrogate value) {
        return Color.FromArgb(value.Value);
    }
    public static explicit operator ColorSurrogate(Color value) {
        return new ColorSurrogate(value.ToArgb());
    }
}
[ProtoContract]
class Foo {
    [ProtoMember(1)]
    public Color Color { get; set; }
}

class Program {
    static void Main() {
        RuntimeTypeModel.Default.Add(typeof(Color), false)
            .SetSurrogate(typeof(ColorSurrogate));

        var foo = new Foo { Color = Color.Firebrick };
        var clone = Serializer.DeepClone(foo);
    }
}
于 2013-04-29T14:53:20.787 回答