簡體   English   中英

protobuf-net 是否支持 C# 9 位置記錄類型?

[英]Does protobuf-net support C# 9 positional record types?

我正在嘗試將 protobuf-net 與 C# 位置記錄類型一起使用,我遇到了這個異常:

10:18:48.048 [EROR] #010 (Microsoft.AspNetCore.Server.Kestrel) Connection id ""0HM4NDHMUB3C6"", Request id ""0HM4NDHMUB3C6:00000003"": An unhandled exception was thrown by the application.
Grpc.Core.RpcException: Status(StatusCode="Internal", Detail="Error starting gRPC call. ProtoException: No parameterless constructor found for Bidirectional.Demo.Common.Contracts.Server.GetServerProcessI
nfo.GetServerProcessInfoResponse", DebugException="ProtoBuf.ProtoException: No parameterless constructor found for Bidirectional.Demo.Common.Contracts.Server.GetServerProcessInfo.GetServerProcessInfoResp
onse
   at ProtoBuf.Internal.ThrowHelper.ThrowProtoException(String message, Exception inner) in /_/src/protobuf-net.Core/Internal/ThrowHelper.cs:line 70
   at ProtoBuf.Meta.TypeModel.ThrowCannotCreateInstance(Type type, Exception inner) in /_/src/protobuf-net.Core/Meta/TypeModel.cs:line 1666
   at proto_12(State& , GetServerProcessInfoResponse )
   at ProtoBuf.Internal.Serializers.SimpleCompiledSerializer`1.ProtoBuf.Serializers.ISerializer<T>.Read(State& state, T value)
   at ProtoBuf.ProtoReader.State.ReadAsRoot[T](T value, ISerializer`1 serializer)
   at ProtoBuf.ProtoReader.State.DeserializeRoot[T](T value, ISerializer`1 serializer)
   at ProtoBuf.Meta.TypeModel.Deserialize[T](ReadOnlySequence`1 source, T value, Object userState)
   at ProtoBuf.Grpc.Configuration.ProtoBufMarshallerFactory.ContextualDeserialize[T](DeserializationContext context)

這就是 GetServerProcessInfoResponse 的樣子:

[ProtoContract]
public record GetServerProcessInfoResponse(
    [property: ProtoMember(1)] TimeSpan TotalProcessorTime,
    [property: ProtoMember(2)] TimeSpan UserProcessorTime,
    [property: ProtoMember(3)] TimeSpan PrivilegedProcessorTime,
    [property: ProtoMember(4)] string CurrentMemoryUsage,
    [property: ProtoMember(5)] string PeakMemoryUsage,
    [property: ProtoMember(6)] int ActiveThreads
);

如果我將 GetServerProcessInfoResponse 更改為具有可獲取和可設置屬性的常規 C# class ,則代碼可以正常工作。 但是,我希望記錄也可以工作,因為它們避免了很多可空性警告。 System.Text.Json 支持例如反序列化記錄,這必須克服相同的限制。

我在文檔、問題或 StackOverflow 上找不到任何東西,所以也許我不擅長搜索,或者答案可能還沒有。 :-)

protobuf-net 存儲庫似乎也沒有任何單元測試嘗試序列化/反序列化 c# 記錄,它只包含“RecordTypeTests”,它似乎正在檢查是否可以克隆記錄?

是的,有兩種不同的方式。

使用您現有的代碼,最簡單的選擇是告訴 protobuf-net 執行 voodoo 以克服沒有可用構造函數的事實; 幸運的是,這很簡單:

[ProtoContract(SkipConstructor = true)]
public record GetServerProcessInfoResponse(
    [property: ProtoMember(1)] TimeSpan TotalProcessorTime,
    [property: ProtoMember(2)] TimeSpan UserProcessorTime,
    [property: ProtoMember(3)] TimeSpan PrivilegedProcessorTime,
    [property: ProtoMember(4)] string CurrentMemoryUsage,
    [property: ProtoMember(5)] string PeakMemoryUsage,
    [property: ProtoMember(6)] int ActiveThreads
);

但是,隨着 v3 代碼的最新版本,它還將推斷在純位置記錄的情況下具體嘗試做什么,即以下內容也應該工作,並且或多或少意味着相同的事情(作為一個微小的細節:在這種情況下,它實際上會使用構造函數,而不是通過 voodoo 創建一個實例然后踩踏值):

public record GetServerProcessInfoResponse(
    TimeSpan TotalProcessorTime,
    TimeSpan UserProcessorTime,
    TimeSpan PrivilegedProcessorTime,
    string CurrentMemoryUsage,
    string PeakMemoryUsage,
    int ActiveThreads
);

記錄將起作用,正如評論和 Marc 在此處的回答所示,問題出在構造函數上,而不是記錄類型。

記錄類型只是類,具有編譯器生成的代碼和屬性。

要顯示到達所需位置的不同方式,您可以添加無參數構造函數。 是的,這比單純的記錄聲明要多一點工作,但是如果你被一個不支持參數化構造函數的 ProtoBuf 版本困住,並且你不想像 Marc 顯示的那樣繞過構造函數,這里有一個不同的選擇:

[ProtoContract]
public record GetServerProcessInfoResponse(
    [property: ProtoMember(1)] TimeSpan TotalProcessorTime,
    [property: ProtoMember(2)] TimeSpan UserProcessorTime,
    [property: ProtoMember(3)] TimeSpan PrivilegedProcessorTime,
    [property: ProtoMember(4)] string CurrentMemoryUsage,
    [property: ProtoMember(5)] string PeakMemoryUsage,
    [property: ProtoMember(6)] int ActiveThreads
)
{
    public GetServerProcessInfoResponse() : this(default, default, default, default, default, default) { }
}

這允許您使用基本的位置記錄聲明,但允許您添加 ProtoBuf <3 想要的無參數構造函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM