Kotlin DSL中@MyDslMarker的多目标应用及作用技术问询
前提条件
按设计,@DslMarker注解仅能应用于注解类(annotation class)。但自定义注解(如annotation class MyDslMarker)后,可无限制地应用于任意目标。
在Kotlin文档、HTML库、社区示例中,@MyDslMarker的主要应用目标是类(或对象),仅能找到1-2处直接应用于函数的案例,暂无属性等其他目标的应用记录。
常用用法
@DslMarker专为限制内部lambda中对外部上下文接收器的隐式访问而设计,通常间接应用于表示上下文的类。若上下文类来自第三方库无法直接注解,可通过如下方式处理(简化版):
@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE) // 新增目标"TYPE" @DslMarker annotation class MyDslMarker // 无法在此处应用注解,因为它不属于我们的代码库 class ThirdPartyClassContext { fun doPrint() = println("Third-party") } @MyDslMarker class OuterContext { // 应用于接收器类型 fun third(init: (@MyDslMarker ThirdPartyClassContext).() -> Unit) { ThirdPartyClassContext().init() //... } } @MyDslMarker class OuterThing fun outerThing(init: OuterContext.() -> Unit): OuterThing { val context = OuterContext() context.init() return OuterThing() // 实际代码中更可能是这样: // return OuterThing(context), // 不过这不是重点 } fun main() { outerThing { third { doPrint() // 符合预期:由于接收器限制,无法在此上下文隐式调用'fun third(init: (ThirdPartyClassContext).() -> Unit): Unit' third { } } } }
这是常见场景,相关说明可参考社区讨论。
但目前仅讨论了类/类型两种@MyDslMarker应用场景,暂无可靠资料涉及函数、属性等其他目标。
为何值得关注
- 文档既未禁止也未提及其他目标的应用,因此函数、属性等目标可能存在类似第三方类类型注解的有效场景。
- 将
@MyDslMarker应用于Context类的方法后,IDE中该方法显示为紫色,说明如下两种写法存在差异:
fun third(init: (@MyDslMarker ThirdPartyClassContext).() -> Unit) { ThirdPartyClassContext().init() }

和
@MyDslMarker fun third(init: (@MyDslMarker ThirdPartyClassContext).() -> Unit) { ThirdPartyClassContext().init() }

核心问题
- 上述示例中,除IDE颜色外,实际行为是否有变化?
- 若有变化,对应的应用场景是什么?
- 理论上可应用于函数、属性等任意目标,这种做法是否实用?若实用,应用方式是什么?
// 至少可以使用这些目标: @Target( AnnotationTarget.CLASS, AnnotationTarget.TYPE, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.PROPERTY_GETTER ) @DslMarker annotation class MyDslMarker
遗憾的是,官方文档及相关示例信息匮乏,希望获取相关技术见解,为更多开发者提供参考。
内容的提问来源于stack exchange,提问作者Tim Korelov
相关产品推荐
相关产品推荐

