【问题标题】:How to declare decimal object in gRPC same as C#如何在 gRPC 中声明与 C# 相同的十进制对象
【发布时间】:2020-12-20 11:32:21
【问题描述】:

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

public class SalarySchedule
{
    public decimal Salary { get; set; }
    public DateTime? SalaryDate { get; set; }
}

我们在 proto 文件中实现了这一点

message SalarySchedule
{
    // TODO: How to define this double to decimal
    double Salary = 1;
    google.protobuf.Timestamp SalaryDate =2;
}

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

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

【问题讨论】:

标签: c# protocol-buffers grpc


【解决方案1】:

有一个提议的 Money 类型经过了一些讨论,但还没有成为“众所周知的”protobuf 类型。

现在,老实说,我建议只使用string。我不知道您使用的是 Google 实现还是 protobuf-net.Grpc(内置但允许“代码优先”使用),但如果您使用的是后者(protobuf-net.Grpc)和 protobuf -net V3,您可以使用[CompatibilityLevel(...)] 指定级别300 或更高级别,并且它将decimal 视为string 用于序列化目的。如果您使用的是 Google 的 .proto 方法,我会手动应用转换,确保使用不变的文化。

【讨论】:

  • 谢谢你的解释,马克。我正在使用谷歌的 .proto 方法。如果我使用字符串类型并手动转换它,如果我最终计算大量集合,会不会对性能造成开销?
  • @Oxygen 你在谷歌实现中的任何类型都有这个问题,因为所有message 类型都变成class,除非明确处理——这不是AFAIK;直接支持double 类型,但是:对于货币价值来说是一个糟糕的选择
  • @Oxygen 注意:protobuf-net 处理这个没有分配(它在内部处理类型),但是:这是一个不平凡的代码更改
【解决方案2】:

microsoft 回答了这个问题。 定义消息 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;
}

然后将 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);
    }
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-19
  • 2015-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多