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で多くのことを行うことができません。RGB

ただし、あなたの考えにはメリットがあります-これは既存の自動タプル機能と非常に似ています-主な違いは、自動タプルコードがすべての明白なメンバーに一致するコンストラクターを必要とすることです。Colorにはそのようなコンストラクターはありませんが、タプル コードを拡張して、コンストラクターだけでなくファクトリ メソッドを使用できるようにすることが可能かどうかを確認することは、一見の価値があります。

ただし、現時点では (コードを変更することなく)、おそらく 2 つの実行可能なオプションがあります。

  • プライベートフィールドをシリアル化し、コンストラクターをスキップするようにモデルに指示します。
  • 代理を使う

おそらく後者の方が簡単だと思います。たとえば、次のように動作します (固定の 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 に答える