我正在尝试使用Wicket的操作符,这很痛苦。
我最想要的功能是使用一元“+”来add()
一个组件。
但是需要在每个MarkupContainer
后代的上下文中工作。
使用应该是这样的:
class SomePage() : WebPage() {
init {
// SomePage{} context
+Label("someLabel","Some label")
// instead of this.add(Label("someLabel","Some label"))
+object : StatelessForm<Unit>("someForm") {
init {
// StatelessForm{} context
+Label("fieldLabel","Field label")
+RequiredTextField("someField")
}
}
}
}
现在可以在没有子类化的情况下实现这一点吗?我想要的一些虚构的语法:
extend org.apache.wicket.MarkupContainer {
operator fun<T: Component> T.unaryPlus():T {
// add() is called as a method of a MarkupContainer instance
add(this) // this@MarkupContainer.add(this@unaryPlus)
return this
}
}
答案 0 :(得分:2)
在此上下文中使用unaryPlus
运算符(+Component
)更难,因为一元暗示,它是单个操作数运算符(单个输入)。但是有一种hacky解决方案:
class ExtOf<out T : MarkupContainer>(val self: T) {
companion object {
private val lastConfiguredContainer = ThreadLocal<ExtOf<MarkupContainer>?>()
fun <T : MarkupContainer> configure(container: T, configurer: ExtOf<T>.() -> Any?): T {
val currentLast = lastConfiguredContainer.get()
try {
val newCurrent = ExtOf(container)
lastConfiguredContainer.set(newCurrent)
newCurrent.configurer()
} finally {
lastConfiguredContainer.set(currentLast)
}
return container
}
}
operator fun <T2 : Component> T2.unaryPlus(): T2 {
val container = lastConfiguredContainer.get()
container!!.self.add(this) //TODO throw a nice exception explaining how ot use the `configure`
return this
}
}
fun <T : MarkupContainer> T.configure(configurer: ExtOf<T>.() -> Any?) = ExtOf.configure(this, configurer)
以上维护MarkupContainer
私有变量中上次配置的ThreadLocal
的信息,该变量用于为add
方法提供接收方。
然后你可以写:
class SomePage() : WebPage() {
init {
configure {
+Label("someLabel", "Some label")
+StatelessForm<Unit>("someForm").configure {
// StatelessForm{} context
+Label("fieldLabel", "Field label")
+RequiredTextField<Long>("someField")
}
}
}
}
正如我上面提到的,解决方案虽然有效,但远非漂亮。它可能会令人困惑(因为经常会重载运算符)所以我建议使用常规add
,如下所示:
class SomePage() : WebPage() {
init {
add(
Label("someLabel", "Some label"),
StatelessForm<Unit>("someForm").apply {
// StatelessForm{} context
add(
Label("fieldLabel", "Field label"),
RequiredTextField<Long>("someField")
)
}
}
}
}
我想理想情况下会有一个类似于anko的库,但是对于检票口。
答案 1 :(得分:-1)
我相信这是不可能的
问题是unaryPlus操作员的乐趣不能有任何参数。你想在MarkupContainer类中使用unaryPlus,但你也想添加组件(其他类,其他参考技术可能是一个参数)
我看到它可以工作的唯一方法是使用子类化(组件子类MarkupContainer)和unaryPlus perator扩展到MarkupContainer
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<corners
android:bottomLeftRadius="8dip"
android:topLeftRadius="8dip"/>
<padding
android:bottom="0dip"
android:left="0dip"
android:right="0dip"
android:top="0dip"/>
</shape>