使用带有 protobuf-net 异常的代理对 List<T> 进行序列化

Posted

技术标签:

【中文标题】使用带有 protobuf-net 异常的代理对 List<T> 进行序列化【英文标题】:Serializing List<T> using a surrogate with protobuf-net exception 【发布时间】:2013-02-10 09:23:22 【问题描述】:

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

代理是这样设置的:

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

我的班级:

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,一切正常。

你能告诉我我做错了什么吗?

谢谢。

【问题讨论】:

如果无用则忽略注释,只是想提供帮助,但我从未使用过协议缓冲区。无论如何,问题似乎很基本,这是否为您指明了正确的方向? ***.com/questions/6498438/… 【参考方案1】:

向隐式运算符转换添加空检查似乎可以解决问题,即:

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);

【讨论】:

【参考方案2】:

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

if(value == null) return null;

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

【讨论】:

以上是关于使用带有 protobuf-net 异常的代理对 List<T> 进行序列化的主要内容,如果未能解决你的问题,请参考以下文章

带有枚举的 Protobuf-net 反序列化异常

protobuf-net、版本控制和代理类型的最佳实践

使用带有标志枚举的 ProtoBuf-Net 时出错

protobuf-net:反序列化 Guid 属性的错误线型异常

具有代理和继承层次结构的 protobuf-net v3

有没有办法在 protobuf-net 代理类中定义替代转换函数(从/到接口)