如何使用protobuf网与不可变的值类型? [英] How to use protobuf-net with immutable value types?

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

问题描述

假设我有一个不变的值类型是这样的:

Suppose I have an immutable value type like this:

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

public MyValueType(int x, int z)
    : this()
{
    _x = x;
    _z = z;
}

// this constructor is used for deserialization
public MyValueType(SerializationInfo info, StreamingContext text)
    : this()
{
    _x = info.GetInt32("X");
    _z = info.GetInt32("Z");
}

[DataMember(Order = 1)]
public int X
{
    get { return _x; }
}

[DataMember(Order = 2)]
public int Z
{
    get { return _z; }
}

public static bool operator ==(MyValueType a, MyValueType b)
{
    return a.Equals(b);
}

public static bool operator !=(MyValueType a, MyValueType b)
{
    return !(a == b);
}

public override bool Equals(object other)
{
    if (!(other is MyValueType))
    {
        return false;
    }

    return Equals((MyValueType)other);
}

public bool Equals(MyValueType other)
{
    return X == other.X && Z == other.Z;
}

public override int GetHashCode()
{
    unchecked
    {
        return (X * 397) ^ Z;
    }
}

// this method is called during serialization
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    info.AddValue("X", X);
    info.AddValue("Z", Z);
}

public override string ToString()
{
    return string.Format("[{0}, {1}]", X, Z);
}
}



它的工作原理与BinaryFormatter的或DataContractSerializer的,但是当我尝试与protobuf网( http://code.google.com/p/protobuf-net/ 使用)串行我得到这个错误:

It works with BinaryFormatter or DataContractSerializer but when I try to use it with protobuf-net (http://code.google.com/p/protobuf-net/) serializer I get this error:

无法将更改应用于财产
ConsoleApplication.Program + MyValueType.X

Cannot apply changes to property ConsoleApplication.Program+MyValueType.X

如果我申请制定者的属性标记数据成员属性,它将工作,但那么它打破这个值类型的不变性,这就是不希望给我们。

If I apply setters to the properties marked with DataMember attribute it will work but then it breaks immutability of this value type and that's not desirable to us.

有谁知道我需要做的就是它的工作?我注意到,还有的ProtoBu.Serializer.Serialize方法,需要在SerializationInfo中和的StreamingContext过载,但我还没有实现ISerializable接口的上下文之外使用它们,所以如何在使用它们的代码示例!这种情况下将非常感激。

Does anyone know what I need to do to get it work? I've noticed that there's an overload of the ProtoBu.Serializer.Serialize method which takes in a SerializationInfo and a StreamingContext but I've not use them outside of the context of implementing ISerializable interface, so any code examples on how to use them in this context will be much appreciated!

谢谢,

编辑:让我挖出了一些旧的MSDN文章和得到了更好地了解在何处以及如何被使用的SerializationInfo和的StreamingContext,但是当我试图做到这一点:

so I dug up some old MSDN article and got a better understanding of where and how SerializationInfo and StreamingContext is used, but when I tried to do this:

var serializationInfo = new SerializationInfo(
    typeof(MyValueType), new FormatterConverter());
ProtoBuf.Serializer.Serialize(serializationInfo, valueType);



事实证明,在序列化< T> 方法只允许引用类型,是有一个特别的原因?它因为我能够通过序列化引用类型暴露值类型似乎有点怪怪的。

it turns out that the Serialize<T> method only allows reference types, is there a particular reason for that? It seems a little strange given that I'm able to serialize value types exposed through a reference type.

推荐答案

的protobuf的哪个版本-net您使用的?如果你是最新的V2版本,它应该与此自动处理。如果我还没有部署该代码的是,我将在稍后更新下载领域,但本质上,如果你的类型是缦(无属性),它会检测你使用的是常见的元组彭定康,并决定(从构造)的 X (构造函数参数)/ X (财产)为字段1,和ž / 以Z 是2场。

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;



(或者 [数据成员(令= N)] 上的字段)

哪些应该工作,取决于信任级别。我的什么也没有的没有完成的概括构造函数代码归因场景。这并不难,但我想先推基本情况,然后改进它。

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.

我添加了以下两个样本/测试的with完整的代码的:

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<MyValueTypeAsTuple>(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<MyValueTypeViaFields>(ms);
            Assert.AreEqual(123, clone.X);
            Assert.AreEqual(456, clone.Z);
        }
    }



另外:

Also:

事实证明,Serialize方法只允许引用类型

it turns out that the Serialize method only allows reference types

是的,这是关系到拳击模型等V1的设计限制;这不再适用与V2。

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

另外请注意,protobuf网没有的本身的消耗 ISerializable的(虽然它可以用于的实施 ISerializable的)。

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

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

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