c# - 为什么protobuf-net在反序列化过程中调用了属性的getter但尚未调用setter

标签 c# .net protobuf-net

我有一个依赖于对象有效状态的属性。我在创建对象期间或在 OnDeserialized 函数中确保这一点。

现在我在 protobuf-net 反序列化过程中遇到了一个神奇的异常,因为该对象尚未生效,因为在反序列化过程中已经调用了该属性的 getter。既没有调用 setter,也没有调用 OnDeserialized 方法(调用了 OnDeserializing!)

我确实从 DataContractSerializer 进行了转换,所以 SkipConstructor 是为了确保相同的行为(我不想删除它)。代码看起来大致像这样:

[ProtoContract(SkipConstructor = true, EnumPassthru = true)]
public class MyClass
{
    [OnSerializing]
    [ProtoBeforeSerialization]
    private void OnSerializing(StreamingContext c)
    {
        // first in here
    }

    [OnSerialized]
    [ProtoAfterSerialization]
    private void OnSerialized(StreamingContext c)
    {
        //
    }

    [ProtoMember(1)]
    private AnotherClass[] NetworkValues
    {
        get {   /* Why here after OnSerializing? */ }
        set { }
    }
}

我不明白。反序列化时getter有什么用?

最佳答案

两个原因

首先:Protocol Buffers 本质上将反序列化定义为“合并”——允许将数据合并到现有对象中,并允许连接两个字节流以实现合并功能。因此,因为它假设它正在进行合并,默认情况下 protobuf-net 正在做的事情,在列表的情况下,是

  • 获取现有列表,如果有的话;否则创建一个新列表
  • 向此列表添加任何新元素(已有的或新的)
  • 如果列表发生变化则将其分配给属性

可以通过在 [ProtoMember] 上将 OverwriteList 属性设置为 true 来覆盖此行为,这使得它始终将属性视为新列表(因此:先前存在的项目将丢失)


其次,该库需要支持一种非常常见的模式——只读列表访问器。这并不是数组真正需要的,但大部分代码都适用于两者 - 但本质上:

private readonly List<AnotherClass> _networkValues = new List<AnotherClass>();
[ProtoMember(1)]
public List<AnotherClass> NetworkValues => _networkValues;

在这种情况下,库获取列表的唯一机制是:获取。

作为旁注:该库还希望在这种情况下避免不必要的列表分配,因此即使一个setter,它也不希望创建一个新列表。但同样 - 其中大部分不适用于数组,因为数组总是需要重新分配以调整它们的大小。

关于c# - 为什么protobuf-net在反序列化过程中调用了属性的getter但尚未调用setter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52535814/

相关文章:

c# - 在 C# 中编写多个构造函数重载的最佳方法

c# - 使用 C# 创建 3D 矩形

c# - C#.net 2.0 中用于将 Datacolumn 转换为分割字符串的任何内置函数

c# - 条件编译和框架目标

c# - 如果使用 Entity Framework ,如何简化

c# - PerfView:分析应用程序的性能,包括数据库调用

.NET 检测线程从外部代码退出?

c# - 通过 protobufnet 从 Redis 反序列化大量用户定义对象时出现性能问题

c# - protobuf 网络 : how to represent DateTime in C#?

c# - IPC 使用 Protobuf 和内存映射文件 C#