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 . Thus your Account record can be deserialized by 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.