0

例如,我的原型模式中有一些枚举:

enum E1 {
     UNKNOWN = 0;
     OPTION_1 = 1;
     OPTION_2 = 2;
     OPTION_3 = 3;
}

enum E2 {
     UNKNOWN = 0;
     ANOTHER_OPTION_1 = 1;
     ANOTHER_OPTION_2 = 2;
     ANOTHER_OPTION_3 = 3;
}

message M {
    E1 my_enum_1 = 1;
    E2 my_enum_2 = 2;
}

我可以通过提供scalaPB TypeMappers 来生成带有字符串而不是枚举的 scala 类:

TypeMapper(_.name)(E1.fromName(_).get)
TypeMapper(_.name)(E2.fromName(_).get)

但我不想为任何单个枚举复制粘贴相同的 TypeMappers

有没有办法为所有枚举只制作一个 TypeMapper scalaPB

4

2 回答 2

2

是的,这是可以做到的。

如果你想让 ScalaPB 对包中的所有枚举使用字符串,你可以添加包范围的选项文件来告诉 ScalaPB 将每个枚举的 scala-type 设置为String使用字段转换

// options.proto:
syntax = "proto3";

import "scalapb/scalapb.proto";

option (scalapb.options) = {
  scope: PACKAGE,
  field_transformations : [
    {
      when : {
        type: TYPE_ENUM
      }
      set : {[scalapb.field] {type : 'String'}}
    }
}

下一步是为所有枚举定义一个类型映射器。借用伊万的回答,这可以定义如下:

implicit def enumMapper[E <: GeneratedEnum](implicit ec: GeneratedEnumCompanion[E]) =
  TypeMapper[E, String](_.name)(ec.fromName(_).get)

如果将上面的代码添加到与生成代码相同的包中的包对象中,或者使用importScalaPB中的选项导入,则会在隐式搜索中找到类型映射器。

于 2022-02-18T21:13:18.633 回答
1

您不能完全避免为您拥有TypeMapper的每种enum类型进行定义。但是您可以创建一个辅助方法来创建TypeMapper实例。

例如

import scalapb.GeneratedEnum
import scalapb.GeneratedEnumCompanion
import scalapb.TypeMapper

def enumMapper[E <: GeneratedEnum: GeneratedEnumCompanion] = {
  TypeMapper[E, String](_.name)(implicitly[GeneratedEnumCompanion[E]].fromName(_).get)
}

- -更新 - -

在@thesamet 评论之后,如果您添加implicit到上面的方法并使其在您的隐式上下文中可用,它将起作用。

这可以使用以下编译的代码进行测试

implicit def enumMapper...

val Enum1Mapper = implicitly[TypeMapper[E1]]

于 2022-02-18T18:59:15.327 回答