Kotlin, how to retrieve field value via reflection - reflection

So I have hundreds of fields in a couple of classes and I'd like to write some methods on them where they automatically println each field and its corresponding value
At the moment I have this:
inner class Version(val profile: Profile) {
#JvmField val MINOR_VERSION = glGetInteger(GL_MINOR_VERSION)
fun write(file: File? = null) {
//file.printWriter().use { out -> out.pri }
this::class.java.fields.forEach {
println(it.isAccessible)
println(it.getInt(it)) }
}
}
But this is what I get:
false
Exception in thread "main" java.lang.IllegalArgumentException: Can not set final int field uno.caps.Caps$Version.MINOR_VERSION to java.lang.reflect.Field
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
at sun.reflect.UnsafeQualifiedIntegerFieldAccessorImpl.getInt(UnsafeQualifiedIntegerFieldAccessorImpl.java:58)
Any idea?

Instead of using Java fields and Java reflection code, you can also use Kotlin properties and Kotlin reflection classes:
class Reflector {
val Foo = 1;
fun printFields() {
this::class.memberProperties.forEach {
if (it.visibility == KVisibility.PUBLIC) {
println(it.name)
println(it.getter.call(this))
}
}
}
}

It seems that you are passing the Field variable it as a parameter getInt whereas the parameter should be the object the field belongs to this:
From the Javadoc for Field.getInt(Object obj):
obj - the object to extract the int value from
Perhaps this is what you meant to do:
class Reflector {
#JvmField val Foo = 1;
fun printFields() {
this.javaClass.fields.forEach {
println(it.isAccessible)
println(it.getInt(this))
}
}
}
fun main(args : Array<String>) {
Reflector().printFields()
}

Related

Mono.Cecil AddInterfaceImplementation equivalent?

I am working on Mono.Cecil codegen util, and I want to preform following operation:
Loop through types
If type contains X attribute:
- Add ITestInterface implementation (where ITestInterface has defined some methods)
// For reference
public interface ITestInterface
{
void Something();
int IntSomething();
}
// Expected result, if type contains X attribute:
// Before codegen:
[X]
public class CodeGenExample
{
}
// After codegen
[X]
public class CodeGenExample : ITestInterface
{
public void Something()
{
// some stuff
}
public int IntSomething()
{
// do some stuff
return 0;
}
}
I have seen that .NET Reflection has a AddInterfaceImplementation method (https://learn.microsoft.com/pl-pl/dotnet/api/system.reflection.emit.typebuilder.addinterfaceimplementation?view=net-5.0).
Is there a Mono.Cecil equivalent or a workaround for this & how to use it?
That can be achieved by:
Iterating over all types defined in the assembly
Checking which types have the attribute applied to
Injecting the methods.
As an example you can do something like:
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace inject
{
interface IMyInterface
{
int Something();
}
class MarkerAttribute : Attribute {}
[Marker]
class Foo
{
}
class Program
{
static void Main(string[] args)
{
if (args.Length == 1)
{
using var a = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location);
var interfaceToImplement = a.MainModule.GetType("inject.IMyInterface");
foreach(var t in a.MainModule.Types)
{
if (t.HasCustomAttributes && t.CustomAttributes.Any(c => c.Constructor.DeclaringType.Name == "MarkerAttribute"))
{
System.Console.WriteLine($"Adding methods to : {t}");
var something = new MethodDefinition("Something", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, a.MainModule.TypeSystem.Int32);
something.Body = new Mono.Cecil.Cil.MethodBody(something);
var il = something.Body.GetILProcessor();
il.Emit(OpCodes.Ldc_I4, 42);
il.Emit(OpCodes.Ret);
t.Methods.Add(something);
// Add the interface.
t.Interfaces.Add(new InterfaceImplementation(interfaceToImplement));
var path = typeof(Program).Assembly.Location + ".new";
a.Write(path);
System.Console.WriteLine($"Modified version written to {path}");
}
}
}
else
{
object f = new Foo();
IMyInterface itf = (IMyInterface) f;
System.Console.WriteLine($"Something() == {itf.Something()}");
}
}
}
}
Another potential solution is to have the methods implemented in an internal class and copying over their method bodies.
As a side note, these are 2 online tools you can use to explore/learn more about CIL, Mono.Cecil, C#:
Sharplab.io
Cecilifier (disclaimer: I'm the author of this one)
That being said if you can use C# 9.0 you may be able to leverage the new Source Generators feature.

TypeScript Compiler API: How to get type with resolved type arguments?

I want to merge class declarations in a .dt.s file to generate a cleaner public API. I am stuck on how to make this work with generic type arguments. Let's say I have:
class A1<T> { // Non-exported class I want to hide
data?: T;
}
export class B1 extends A1<string> {
}
Ideally, I want to turn this into:
export class B1 {
data?: string;
}
I can get the type of A1 and then copy its members. But how do get a resolved version of A1 that uses string instead of T?
For reference, this is my current code:
for (const heritageClause of node.heritageClauses) {
for (const type of heritageClause.types) {
if (isExported(type.modifiers)) {
exportedTypes.push(type);
} else {
const privateType = typeChecker.getTypeAtLocation(type);
if (privateType?.symbol?.members) {
privateType.symbol.members.forEach((definition, memberName) => {
if (!currentMembers || !currentMembers.has(memberName)) {
additionalMembers.push(...definition.declarations);
}
}
});
}
}
}
I believe the method you are looking for is TypeChecker#getTypeOfSymbolAtLocation(symbol, node).
The following should get the resolved type of string | undefined:
// by the way, recommend renaming `type` to `typeNode` to avoid confusion
typeChecker.getTypeOfSymbolAtLocation(privateType.getProperties()[0], type);

How can I concat a call that returns an array and multiple calls for each element of this array?

Sorry if that title is not clear enough but I didn't know how to sum it up in one sentence.
I have a webservice that returns an ArrayList of objects named Father.
The Father object is structured like this:
class Father {
ArrayList<Child> children;
}
I have another webservice that returns me the detail of the object Child.
How can I concat the first call that returns me the arraylist of Father and the multiple calls for the multiple objects Child ?
So far I can make the calls separately, like this:
Call for ArrayList of Father
myRepository.getFathers().subscribeOn(Schedulers.io())
.observeOn(Schedulers.io()).subscribeWith(new DisposableSingleObserver<List<Father>>() {
})
multiple call for ArrayList of Child
childListObservable
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.flatMap((Function<List<Child>, ObservableSource<Child>>) Observable::fromIterable)
.flatMap((Function<Child, ObservableSource<Child>>) this::getChildDetailObservable)
.subscribeWith(new DisposableObserver<Child>() {
// do whatever action after the result of each Child
}))
Prerequisite
Gradle
implementation("io.reactivex.rxjava2:rxjava:2.2.10")
testImplementation("io.mockk:mockk:1.10.0")
testImplementation("org.assertj:assertj-core:3.11.1")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.3.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.3.1")
Classes / Interfaces
interface Api {
fun getFather(): Single<List<Father>>
fun childDetailInfo(child: Child): Single<ChildDetailInfo>
}
interface Store {
fun store(father: Father): Completable
fun store(child: ChildDetailInfo): Completable
}
class ApiImpl : Api {
override fun getFather(): Single<List<Father>> {
val child = Child("1")
val child1 = Child("2")
return Single.just(listOf(Father(listOf(child, child1)), Father(listOf(child))))
}
override fun childDetailInfo(child: Child): Single<ChildDetailInfo> {
return Single.just(ChildDetailInfo(child.name))
}
}
data class Father(val childes: List<Child>)
data class Child(val name: String)
data class ChildDetailInfo(val name: String)
Solution
val fathersStore = api.getFather()
.flatMapObservable {
Observable.fromIterable(it)
}.flatMapCompletable {
val detailInfos = it.childes.map { child ->
api.childDetailInfo(child)
.flatMapCompletable { detail -> store.store(detail) }
}
store.store(it)
.andThen(Completable.concat(detailInfos))
}
On each emit of a List of fathers, the list is flatten. The next opreator (flatMapCompletable) will take an Father. The completable will get the details of each Child with Api#childDetailInfo. The result is build by calling the API one by one. There is no concurrency happening wegen "concat". When the father is stored sucessfully, the childs will be stored as-well, when retrieved successfully. If one of the API-calls fails (e.g. network) everything fails, because the onError will be propgated to the subscriber.
Test
#Test
fun so62299778() {
val api = ApiImpl()
val store = mockk<Store>()
every { store.store(any<Father>()) } returns Completable.complete()
every { store.store(any<ChildDetailInfo>()) } returns Completable.complete()
val fathersStore = api.getFather()
.flatMapObservable {
Observable.fromIterable(it)
}.flatMapCompletable {
val detailInfos = it.childes.map { child ->
api.childDetailInfo(child)
.flatMapCompletable { detail -> store.store(detail) }
}
store.store(it)
.andThen(Completable.concat(detailInfos))
}
fathersStore.test()
.assertComplete()
verify { store.store(eq(Father(listOf(Child("1"), Child("2"))))) }
verify { store.store(eq(Father(listOf(Child("1"))))) }
verify(atLeast = 2) { store.store(eq(ChildDetailInfo("1"))) }
verify(atLeast = 1) { store.store(eq(ChildDetailInfo("2"))) }
}
Please provide next time some classes/ interfaces. When your question contains all vital information, you will get an answer quicker.

How can I get the name of a Kotlin property?

I have the following function to access a property's delegate. It uses Kotlin reflection to get a property's name and Java reflection to get the field.
fun Any.getDelegate<T>(prop: KProperty<T>): Any {
return javaClass.getDeclaredField("${prop.name}\$delegate").let {
it.setAccessible(true)
it.get(this)
}
}
The method is used like this:
val delegate = a.getDelegate(A::b)
However, I would prefer to use it like this:
val delegate = a.b.delegate
The problem with the code above is getting the property name of a.b and getting the instance a from a.b. From what I know about Kotlin, this is probably not possible, however I'd like to see if I can clean up my function at all.
To give a bigger picture of what I'm trying do here's my complete code. I want an observable delegate to which I can add and remove observers using the delegate reference and without creating addition variables.
fun Any.addObservable<T>(prop: KProperty<T>, observer: (T) -> Unit) {
getObservableProperty(prop).observers.add(observer)
}
fun Any.getObservableProperty<T>(prop: KProperty<T>): ObservableProperty<T> {
return getDelegate(prop) as ObservableProperty<T>
}
fun Any.getDelegate<T>(prop: KProperty<T>): Any {
return javaClass.getDeclaredField("${prop.name}\$delegate").let {
it.setAccessible(true)
it.get(this)
}
}
class ObservableProperty<T>(
initialValue: T,
initialObservers: Array<(T) -> Unit> = emptyArray()) : ReadWriteProperty<Any?, T> {
private var value = initialValue
public val observers: MutableSet<(T) -> Unit> = initialObservers.toHashSet()
public override fun get(thisRef: Any?, desc: PropertyMetadata): T {
return value
}
public override fun set(thisRef: Any?, desc: PropertyMetadata, value: T) {
this.value = value
observers.forEach { it(value) }
}
}
class A() {
var b by ObservableProperty(0)
}
fun main(args: Array<String>) {
val a = A()
a.addObservable(A::b) {
println("b is now $it")
}
a.b = 1
a.b = 2
a.b = 3
}
Edit:
I just realized that the function also isn't strict because the property delegate field name is referenced by KProperty name, which doesn't require a strong reference to the enclosing class. Here's an example to demonstrate the problem:
class A() {
var foo by ObservableProperty(0)
}
class B() {
var foo by ObservableProperty(0)
}
fun main(args: Array<String>) {
val a = A()
a.addObservable(B::foo) {
println("b is now $it")
}
a.foo = 1
a.foo = 2
a.foo = 3
}
This compiles and runs without error because A::foo and B::foo both result in a field string of "foo$delegate.
Right now reflection is all we can do to get to the delegate object. We are designing a language feature to have direct access to delegate instance, but it's long way to go.
This is how you get the name of a Kotlin Property (although only with an instance of the class). This part will be useful to anyone arriving at this question purely based off its title.
class Stuff(val thing: String)
val stuff = Stuff("cool stuff")
val thingFieldName = "${stuff.thing}\$delegate"
// value of thingFieldName is now "thing"
In terms of getting the delegate itself easier, they say you can now do this:
class Foo {
var bar: String by ReactiveProperty<String>()
}
val foo = Foo()
val bar = foo.bar
val barDelegate = ... // foo.bar$delegate
See ticket.

In Flex3, what type is an object property?

I have many Flex objects like this one:
public class MyData {
public var time: Date;
public var label: String;
}
I am populating this object from a DB record retrieved via AMF that looks something like this:
{
label: "Label",
incident: "2009-08-15 11:12:14.12233"
}
I want to write a generic value mapper for these object that, given a target object (instance of MyData here) and an input record, will be able to tell that MyData.time is a Date field and perform type mapping automatically. Something like this:
function map(obj, targetType): * {
var newInstance: * = new targetType();
for (var property: String in obj) {
if (getPropertyType(targetType, property) == Date) {
newInstance[property] = parseDate(obj[property]);
}
else {
newInstance[property] = obj[property];
}
}
}
function getPropertyType(type_var: Class, property: String): Class {
// .. this is what I have no idea how to do
}
Can someone fill in the blank here?
You possibly need something like describeType. And maybe you need to use getDefinitionByName() if you want to make to a real object. So something like this for the contents of your function:
var typeXml:XML = describeType(type_var[property]);
return getDefinitionByName(typeXml.type[0].#name);
I haven't compiled it. Just throwing it out there to see if it helps.
You can use the 'is' operator to check the type of an object.
The is operator
function map(obj, targetType): * {
var newInstance: * = new targetType();
for (var property: String in obj) {
if (obj[property] is Date) {
newInstance[property] = parseDate(obj[property]);
}
else {
newInstance[property] = obj[property];
}
}
}
hth
Koen
If you need to map an Object variable to a variable class as MyData you can do the following
public class MyData
{
public var time: Date;
public var label: String;
function map(obj:Object):void
{
for (var property: String in obj)
{
this[property] = obj[property];
}
}
}
Note: The object obj must contain the exact "time" and "label" properties.
Hope it solves your problem

Resources