我该如何为属性定义这些复杂的初始值设定项

时间:2018-04-29 15:27:05

标签: kotlin kotlinpoet

虽然我检查了kotlinpoet代码中的所有测试,但是我没有找到实现下面目标代码的正确方法,或者我不确定我是否使用最佳方法来做到这一点。如果有人能对此提出一些意见,那将非常感激。

这些属性在类

的函数中定义

目标代码1

val outputState = StateType1(iouValue, ourIdentity, otherParty)

我使用以下代码生成上面的代码

.addCode(CodeBlock.of("%L",
    PropertySpec.builder("outputState", ClassName("","StateType1"))
        .initializer(CodeBlock.of("%T(%L, %L, %L)", ClassName("","StateType1"), "iouValue", "ourIdentity", "otherParty"))
        .build()))

但问题是这个outputState可能来自不同的类型,例如,StateType1有3个参数,但StateTyp2可能只有1个参数,我应该如何动态定义我的kotlinpoet代码以生成正确的目标代码。

目标守则2

val txBuilder = TransactionBuilder(notary = notary)
    .addOutputState(outputState, TEMPLATE_CONTRACT_ID)

我没有找到具有这种情况的参考测试用例,在属性的初始化程序之后直接调用它的函数。

1 个答案:

答案 0 :(得分:0)

使用CodeBlock.Builder作为第一个示例,它为您提供了构建CodeBlock的更大灵活性:

fun createConstructorCall(type: TypeName, vararg args: String): CodeBlock {
  val argsCode = args
      .map { CodeBlock.of("%L", it) }
      .joinToCode(separator = ", ", prefix = "(", suffix = ")")
  return CodeBlock.Builder()
      .add("%T", type)
      .add(argsCode)
      .build()
}

val className = ClassName("", "StateType1")
val codeBlock = CodeBlock.of("%L", PropertySpec.builder("outputState", className)
    .initializer(createConstructorCall(className, "iouValue", "ourIdentity", "otherParty"))
    .build())
assertThat(codeBlock.toString()).isEqualTo("""
  |val outputState: StateType1 = StateType1(iouValue, ourIdentity, otherParty)
  |""".trimMargin())

在第二个示例中,我们并没有真正提供任何特殊内容,将代码作为字符串传递,如果需要,可以随意使用占位符进行参数化:

val className1 = ClassName("", "TransactionBuilder")
val codeBlock1 = CodeBlock.of("%L", PropertySpec.builder("txBuilder", className)
    .initializer(
        "%T(notary = notary)\n.addOutputState(outputState, TEMPLATE_CONTRACT_ID)",
        className1)
    .build())
assertThat(codeBlock1.toString()).isEqualTo("""
  |val txBuilder: StateType1 = TransactionBuilder(notary = notary)
  |        .addOutputState(outputState, TEMPLATE_CONTRACT_ID)
  |""".trimMargin())