我有一个依赖于对象有效状态的属性。我在创建对象期间或在 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/