我们可以访问kotlin中任何属性的PropertyMetaData吗?

在kotlin中有一种方法可以从PropertyMetaData外部访问PropertyMetaData吗? 更具体一点,从代表团? 寻找这样的东西:

编辑(现在更合适的例子)

 class Obj(var name : String = "") class Bar { val prop1 : Obj by Inject.inject() // <- can inject() access prop1 without passing it explicitly? val prop2 : Obj by Inject.inject() } object Inject { val injected = arrayListOf<ReadOnlyProperty<Any, Obj>>() fun inject() : ReadOnlyProperty<Any, Obj> { val delegate = Delegates.lazy { Obj("NEED THE DELEGATED PROPERTY'S NAME HERE") // <- like "prop1" "prop2" ... } injected.add(delegate) return delegate } } 

编辑(在1.0.0-beta-1038之后)

此代码片段之前像一个魅力工作(注意:字符串“scrollPlace”没有明确通过使用以前版本的kotlin,因为属性名称“隐式”之前通过):

 val scrollPlace by injectBy<Image>("scrollPlace").replaceBy { val scrollPane = ScrollPane(VerticalGroup().space(12f).center()) scrollPane.setPosition(it.x, it.y) scrollPane.setSize(it.width, it.height) scrollPane } 

在这个例子中,我使用了一些链接。 除了传递一个自定义字符串外,扩展函数injectBy(它是基于接受的答案中建议的模式1)创建一个O2dInjectionClosure(ReadOnlyProperty)实例。 解决方案1)当然会起作用,尽管它不像使用propertyDelgated那样方便,但链接会带来一些麻烦。 至少有一个合适的解决方案还没有出现在我的脑海。 扩展函数replaceBy创建另一个新的O2dInjectionClosure实例:

  public final fun <T : Actor, R : Actor> O2dInjectionClosure<T>.replaceBy(replacer : (replaced : T) -> R) : O2dInjectionClosure<R> { val originalInitializer = this.initializer return O2dInjectionClosure { propName -> ... some transferring of the previous O2dInjectionClosure to this one new } } 

因此,我不知何故想在链接的最后一次调用上做必要的事情,但方便的方式:)。 我希望这是合理的

显然你需要在一个委托对象上调用一些属性的初始化代码。 有几个解决方案:

1)使用属性引用表达式(如bashor所示)获取属性的名称并将其传递给inject

 val prop1: Obj by Inject.inject(Bar::prop1.name) val prop2: Obj by Inject.inject(Bar::prop2.name) 

尽管是明确的,但这是一种冗长且容易出错的方式。

2)在首次访问属性时执行初始化逻辑。 所以Inject本身成为一个属性委托,维护注册属性的地图。 但是,语义上的细微变化可能不适用于您的用例:要在Inject注册属性,至少需要一个get

 class Bar { val prop1: Obj by Inject val prop2: Obj by Inject } object Inject { val injected = hashMapOf<String, ReadOnlyProperty<Any, Obj>>() fun get(obj: Any, metadata: PropertyMetadata): Obj { // getOrPut computes and stores the value for the key if it's not present in the map val property = injected.getOrPut(metadata.name) { Delegates.lazy { Obj(metadata.name) } } return property[obj, metadata] } } 

3)(UPD:不再支持)。使用propertyDelegated方法,这是一个隐藏的和实验性的功能,允许你的属性代理初始化的属性的元数据将使用这个代表访问。 但要小心,这种方法可能会被重新命名,重新设计,甚至在未来版本的Kotlin中被删除。

 class Bar { val prop1: Obj by Inject val prop2: Obj by Inject } object Inject { val injected = hashMapOf<String, ReadOnlyProperty<Any, Obj>>() // Experimental method recognized and called by Kotlin on delegated property initialization fun propertyDelegated(metadata: PropertyMetadata) { injected[metadata.name] = Delegates.lazy { Obj(metadata.name) } } fun get(obj: Any, metadata: PropertyMetadata): Obj { return injected[metadata.name]!!.get(obj, metadata) } }