C# 代码优先 grpc:DateTime 的自定义 protobuf 转换器

C# code first grpc : custom protobuf converter for DateTime

我在 dotnet asp net core 6:

中使用类似的东西
<PackageReference Include="protobuf-net.Grpc.AspNetCore" Version="1.0.152" />
<PackageReference Include="protobuf-net.Grpc.AspNetCore.Reflection" Version="1.0.152" />


[DataContract]
public class TaskItem
{
    //other properties omitted

    [DataMember(Order = 5)]
    public DateTime DueDate { get; set; } = null!;
}

现在,当我使用 grpcurl 调用服务时

"DueDate": {
  "value": "458398",
  "scale": "HOURS"
}

并在生成的proto文件中

import "protobuf-net/bcl.proto"; // schema for protobuf-net's handling of core .NET types

 message TaskItem {
    //other properties omitted
    .bcl.DateTime DueDate = 5;

有没有办法指定一个自定义转换器,以便它序列化为 ISO 8601 字符串,以便更好地支持跨平台(我将有一些 js 客户端,其中有一个字符串是可以的,因为我只需要 new Date(v)d.toISOString()) ?

我知道我可以将 DueDate 声明为字符串,但随后的“问题”是,当我使用 C# 代码优先客户端时,我还需要转换回 DateTime 和字符串...

例如,我可以使用 JSON

执行以下操作
.AddJsonOptions(x =>
{
    x.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});

你问的是非常不同于JSON类型的转换器。作为 the docs explain the standard way of serializing dates is the google.protobuf.Timestamp type. That's defined in the proto file. When you use code-first that file is generated by the open source protobuf-net.Grpc 工具。

要使用 Timestamp 类型,您需要告诉工具使用具有 ProtoMember 属性的 well-known 类型来格式化 属性 :

[ProtoMember(1, DataFormat = DataFormat.WellKnown)]
public DateTime Time { get; set; }

这显示在工具的 Getting Started 文档中。

由于遗留原因,这不是默认设置:

(for legacy reasons, protobuf-net defaults to a different library-specific layout that pre-dates the introduction of .google.protobuf.Timestamp). It is recommended to use DataFormat.WellKnown on DateTime and TimeSpan values whenever possible.