使用具有protobuf-net异常的代理</t>序列化List <t>

时间:2013-02-10 09:23:22

标签: c# null deserialization protocol-buffers protobuf-net

我正在使用protobuf-net(版本2.0.0.621)并且在序列化List类型时遇到问题,其中T是我自己的类(它不管它包含什么)并且为T设置了代理。

代理人设置如下:

ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(MyClass), false).SetSurrogate(typeof(MyClassSurrogate));

MyClass的:

public class MyClass
{
    public int Number { get; set; }
}

[ProtoContract]
MyClassSurrogate
{
    [ProtoMember(1)]
    public int Number { get; set; }
}

然后我创建一个MyClass类型的通用列表,用项填充它并像这样序列化它:

ProtoBuf.Serializer.Serialize(stream, list);

在反序列化时出现问题,我在隐式运算符转换中的代理中一直得到“null”:

static public implicit operator MyClassSurrogate(MyClass myClass)

然后'myClass'为空。

如果我删除代理并使用proto属性装饰MyClass,一切正常。

你能告诉我我做错了吗?

感谢。

2 个答案:

答案 0 :(得分:5)

对隐式运算符转换添加空检查似乎解决了这个问题,即:

public static implicit operator MyClassSurrogate(MyClass myClass)
{
    return myClass != null ? new MyClassSurrogate { Number = myClass.Number } : null;
}

隐式运算符在反序列化时最初调用一次,结果显示为忽略。

完全实施MyClassSurrogate:

[ProtoContract]
public class MyClassSurrogate
{
    [ProtoMember(1)]
    public int Number { get; set; }

    public static implicit operator MyClassSurrogate(MyClass myClass)
    {
        return 
            myClass != null 
            ? new MyClassSurrogate { Number = myClass.Number } 
            : null;
    }

    public static implicit operator MyClass(MyClassSurrogate myClass)
    {
        return new MyClass { Number = myClass.Number };
    }
}

完整序列化/反序列化示例:

var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
model.Add(typeof(MyClassSurrogate), true);
model.Add(typeof(MyClass), false).SetSurrogate(typeof(MyClassSurrogate));
var stream = new System.IO.MemoryStream();
var list = new List<MyClass>();
for (int x = 0; x < 10; x++) list.Add(new MyClass { Number = x });            
ProtoBuf.Serializer.Serialize(stream, list);
stream.Seek(0, SeekOrigin.Begin);
var xs = ProtoBuf.Serializer.Deserialize<List<MyClass>>(stream);
foreach (var x in xs) Debug.WriteLine(x.Number);

答案 1 :(得分:1)

经常使用null值,包括在反序列化期间。您应该能够通过告诉转换运算符将null转换为null来解决此问题:

if(value == null) return null;

考虑到这一点,我可以安全地添加“如果两者都是引用类型,则将null自动转换为null”。