How to use protobuf-net with immutable value types?

后端 未结 2 597
野趣味
野趣味 2021-02-13 16:04

Suppose I have an immutable value type like this:

[Serializable]
[DataContract]
public struct MyValueType : ISerializable
{
private readonly int _x;
private read         


        
2条回答
  •  被撕碎了的回忆
    2021-02-13 16:40

    Which version of protobuf-net are you using? If you are the latest v2 build, it should cope with this automatically. In case I haven't deployed this code yet, I'll update the download areas in a moment, but essentially if your type is unadorned (no attributes), it will detect the common "tuple" patten you are using, and decide (from the constructor) that x (constructor parameter)/X (property) is field 1, and z/Z is field 2.

    Another approach is to mark the fields:

    [ProtoMember(1)]
    private readonly int _x;
    
    [ProtoMember(2)]
    private readonly int _z;
    

    (or alternatively [DataMember(Order=n)] on the fields)

    which should work, depending on the trust level. What I haven't done yet is generalise the constructor code to attributed scenarios. That isn't hard, but I wanted to push the basic case first, then evolve it.

    I've added the following two samples/tests with full code here:

        [Test]
        public void RoundTripImmutableTypeAsTuple()
        {
            using(var ms = new MemoryStream())
            {
                var val = new MyValueTypeAsTuple(123, 456);
                Serializer.Serialize(ms, val);
                ms.Position = 0;
                var clone = Serializer.Deserialize(ms);
                Assert.AreEqual(123, clone.X);
                Assert.AreEqual(456, clone.Z);
            }
        }
        [Test]
        public void RoundTripImmutableTypeViaFields()
        {
            using (var ms = new MemoryStream())
            {
                var val = new MyValueTypeViaFields(123, 456);
                Serializer.Serialize(ms, val);
                ms.Position = 0;
                var clone = Serializer.Deserialize(ms);
                Assert.AreEqual(123, clone.X);
                Assert.AreEqual(456, clone.Z);
            }
        }
    

    Also:

    it turns out that the Serialize method only allows reference types

    yes, that was a design limitation of v1 that related to the boxing model etc; this no longer applies with v2.

    Also, note that protobuf-net doesn't itself consume ISerializable (although it can be used to implement ISerializable).

提交回复
热议问题