我目前这个课程的dsl
类似于建筑能力
class GRLMessage {
var headerMap : MutableMap<String, String> = mutableMapOf()
lateinit var methodType : GRLMethod
lateinit var multipartObject : IGRLMultipart
fun message(closure: GRLMessage.() -> Unit) : GRLMessage {
closure()
return this
}
fun method(closure: GRLMessage.() -> GRLMethod) : GRLMessage {
methodType = closure()
return this
}
fun headers(closure: GRLMessage.() -> Unit) : GRLMessage {
closure()
return this
}
fun header(closure: GRLMessage.() -> Pair<String, String>) : GRLMessage {
var pair = closure()
headerMap.put(pair.first, pair.second)
return this
}
fun multipart(closure: GRLMessage.() -> IGRLMultipart) : GRLMessage {
multipartObject = closure()
return this
}
}
我就像这样测试
class GRLMessageTest {
data class DummyMultipart(val field: String) : IGRLMultipart {
override fun getContent() {
this
}
}
@Test fun grlMessageBuilderTest() {
val grlMessage = GRLMessage().message {
method { GRLMethod.POST }
headers {
header { Pair("contentType", "object") }
header { Pair("objectType", "DummyMultipart") }
}
multipart { DummyMultipart("dummy") }
}
val multipart = DummyMultipart("dummy")
val headers = mapOf(
Pair("contentType", "object"),
Pair("objectType", "DummyMultipart")
)
val method = GRLMethod.POST
assertEquals(multipart, grlMessage.multipartObject)
assertEquals(method, grlMessage.methodType)
assertEquals(headers, grlMessage.headerMap)
}
}
但是尽管提供了
header { Pair("contentType", "object") }
我仍然需要在closure
方法中评估header
并直接评估put
密钥和值到我的MutableMap
fun header(closure: GRLMessage.() -> Pair<String, String>) : GRLMessage {
var pair = closure()
headerMap.put(pair.first, pair.second)
return this
}
是否有更好的方法将条目添加到Map
?
答案 0 :(得分:2)
您的headerMap
是否需要变量?如果没有,您可以将其更改为val并使用headerMap += closure()
。
答案 1 :(得分:1)
添加extension function会使您的流利方法更加流畅:
fun <T: Any> T.fluently(func: ()->Unit): T {
return this.apply { func() }
}
这样你的流利功能总是清楚它的回归:
fun header(closure: GRLMessage.() -> Pair<String, String>) : GRLMessage {
return fluently { headerMap += closure() }
}
这与以下内容完全相同:
fun header(closure: GRLMessage.() -> Pair<String, String>) : GRLMessage {
return this.apply { headerMap += closure() }
}
但扩展功能增加了可读性。
上面我使用@Ruckus给出的答案来解决您向Pair
添加headerMap
的具体问题。但是,对于DSL的其他用例,您可能还想了解其他选项......
您可以使用let
,apply
或with
,这样可以对closure()
调用的结果进行任何类型的分解(可能比{{1}更复杂}} 在将来)。所有这些基本相同,减去它们的结果值:
Pair
如果您想要处理with(closure()) { headerMap.put(this.first, this.second) }
closure().apply { headerMap.put(this.first, this.second) }
closure().let { headerMap.put(it.first, it.second) }
允许可以为空的返回的情况,那么使用let
或apply
很不错,在这种情况下,您可能只想在closure()
时才采取行动}:
null
关于您的代码的其他说明:
closure()?.apply { headerMap.put(this.first, this.second) }
closure()?.let { headerMap.put(it.first, it.second) }
代替val
var
(或类似的lateinit
)似乎很危险,无法在不受控制的生命周期中使用,因为错误信息会让人感到困惑,并且会在某个意外时间发生。未来。可能还有其他方法可以通过DSL链接调用来创建更多的多步语法来解决这个问题您只需在作业的一侧添加类型即可缩短代码,例如:
Delegates.notNull()
而不是
val myMap = mutableMapOf<String, String>()
答案 2 :(得分:0)
现在作为解决方案,我为MutableMap
fun MutableMap<String, String>.put(pair : Pair<String, String>) {
this.put(pair.first, pair.second)
}
这让我这样写了
fun header(closure: GRLMessage.() -> Pair<String, String>) : GRLMessage {
headerMap.put(closure())
return this
}