Protobuf-Net 无法在没有无参数构造函数的情况下反序列化记录
Protobuf-Net Cannot Deserialize Record Without Parameterless Constructor
考虑以下代码示例;我希望能够使用 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: No parameterless constructor found for Example.Account
有没有办法配置反序列化(不使用属性)以允许没有无参数构造函数的记录?
记录的属性默认为init
-only, and as such can actually be set by reflection by protobuf-net. Thus your Account
record can be deserialized by protobuf-net by bypassing the constructor as explained in by Marc Gravell to 。
由于您是在运行时初始化 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; }
}
演示 fiddle here.
考虑以下代码示例;我希望能够使用 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: No parameterless constructor found for Example.Account
有没有办法配置反序列化(不使用属性)以允许没有无参数构造函数的记录?
记录的属性默认为init
-only, and as such can actually be set by reflection by protobuf-net. Thus your Account
record can be deserialized by protobuf-net by bypassing the constructor as explained in
由于您是在运行时初始化 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; }
}
演示 fiddle here.