如何在 gRPC 中声明与 C# 相同的十进制对象

Oxy*_*gen 4 c# protocol-buffers grpc

我们正在将现有的 REST API 服务转换为 gRPC 核心。在迁移现有类时,我们知道 gRPC 没有十进制数据类型。我们在 C# 中有一个类,其定义为

public class SalarySchedule
{
    public decimal Salary { get; set; }
    public DateTime? SalaryDate { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我们在 proto 文件中将其实现为

message SalarySchedule
{
    // TODO: How to define this double to decimal
    double Salary = 1;
    google.protobuf.Timestamp SalaryDate =2;
}
Run Code Online (Sandbox Code Playgroud)

目前,我们使用double作为Salary数据类型。但这导致内部计算出现问题。

您能否指导我们,我们如何将其定义为gRPC 中的小数?

Cle*_*ens 6

微软回答了这个问题。定义消息 DecimalValue:

// Example: 12345.6789 -> { units = 12345, nanos = 678900000 }
message DecimalValue {

    // Whole units part of the amount
    int64 units = 1;

    // Nano units of the amount (10^-9)
    // Must be same sign as units
    sfixed32 nanos = 2;
}
Run Code Online (Sandbox Code Playgroud)

然后将 DecimalValue 转换为十进制,例如使用隐式运算符:

public partial class DecimalValue {
    private const decimal NanoFactor = 1_000_000_000;
    public DecimalValue(long units, int nanos) {
        Units = units;
        Nanos = nanos;
    }

    public static implicit operator decimal(CustomTypes.DecimalValue grpcDecimal) 
        => grpcDecimal.Units + grpcDecimal.Nanos / NanoFactor; 

    public static implicit operator CustomTypes.DecimalValue(decimal value){
        var units = decimal.ToInt64(value);
        var nanos = decimal.ToInt32((value - units) * NanoFactor);
        return new CustomTypes.DecimalValue(units, nanos);
    }
}
Run Code Online (Sandbox Code Playgroud)