Protobuf-Net 无法在没有无参数构造函数的情况下反序列化记录
Posted
技术标签:
【中文标题】Protobuf-Net 无法在没有无参数构造函数的情况下反序列化记录【英文标题】:Protobuf-Net Cannot Deserialize Record Without Parameterless Constructor 【发布时间】:2021-09-04 13:58:40 【问题描述】:考虑以下代码示例;我希望能够使用 protobuf-net 序列化(工作正常)和反序列化(不起作用)Account
记录:
public abstract record State
public abstract ISet<Identity> Identities get;
public SerializedState Serialize()
using MemoryStream stream = new();
Serializer.Serialize(stream, this);
return new SerializedState(stream.ToArray(), GetType());
public sealed record Account(Identity Owner, string Identifier, decimal Balance) : State
public override ISet<Identity> Identities => new HashSet<Identity> Owner;
ProtoBuf 合约配置有效:
RuntimeTypeModel
.Default
.Add<Account>()
.Add(nameof(Account.Owner))
.Add(nameof(Account.Identifier))
.Add(nameof(Account.Balance));
但我得到以下异常:
ProtoBuf.ProtoException:没有为 Example.Account 找到无参数构造函数
有没有办法配置反序列化(不使用属性)以允许没有无参数构造函数的记录?
【问题讨论】:
我认为这个之前的答案应该会有所帮助:***.com/a/65123415/214073 @KijanaWoodard 我直接与 Marc Gravell 进行了交谈~in~。他说继承也是一样,稍微复杂一点,但目前还没有官方回答。 我不认为您可以提供minimal reproducible example 可以吗?我怀疑***.com/a/65123415/214073 的解决方法可以工作,但是您的代码无法编译,所以我不能肯定地说。见dotnetfiddle.net/hSGMnE。 似乎设置MetaType.UseConstructor = false
确实有效,请参阅dotnetfiddle.net/N9siZk。这回答了你的问题了吗?如果没有,你能分享一个minimal reproducible example 显示什么不起作用吗?
【参考方案1】:
记录的属性默认为init
-only,因此实际上可以通过protobuf-net 反射设置。因此,您的Account
记录可以由protobuf-net 反序列化,方法是绕过this answer 中解释的构造函数,由Marc Gravell 到Does protobuf-net support C# 9 positional record types?。
由于您是在运行时为Account
初始化合约,因此请修改您的初始化代码以设置MetaType.UseConstructor = false
,如下所示:
var accountMeta = RuntimeTypeModel
.Default
.Add<Account>()
.Add(nameof(Account.Owner))
.Add(nameof(Account.Identifier))
.Add(nameof(Account.Balance));
accountMeta.UseConstructor = false;
现在你可以这样做了:
var account = new Account(identity, "Foo", 1.1m);
var state = account.Serialize();
var account2 = (Account)Serializer.NonGeneric.Deserialize(state.Type, new MemoryStream(state.Data));
我假设SerializedState
看起来像这样:
public class SerializedState
public SerializedState(byte [] data, Type type) => (Data, Type) = (data, type);
public byte [] Data get; set;
public System.Type Type get; set;
演示小提琴here.
【讨论】:
感谢您的帮助,真的很有帮助!我不认为你可以看看我的下一个问题,你可以吗;-) ***.com/questions/69383475/…以上是关于Protobuf-Net 无法在没有无参数构造函数的情况下反序列化记录的主要内容,如果未能解决你的问题,请参考以下文章
使用非标准构造函数序列化和反序列化对象 - protobuf-net