lundi 3 juin 2019

Getting the values of the nested fields (fields of the object type field) using Java reflection

There's a class which some of its fields are user-defined objects. I'm going to:

  1. Get the Primary class' fields and traverse through them to get their values.

    1.1 When encountering a field with the type of object, go through this object which has its own fields

  2. Get the values of these nested fields (fields of the object type field)

The problem is at step 2; When I get the fields of the object field, couldn't get their values as I need to pass an object to field.get(object) to indicate which object I want the values of the fields being extracted from, But how can I access the current object of our talking field with the type of object?

Here's the code:

public class PrimaryClass {
    String str;
    int num;
    MyClass cls;
}


PrimaryClass primaryObject = new PrimaryClass();

Field[] primaryObjectFields = primaryObject.getClass().getDeclaredFields();

// ... One of the fields is :  MyClass foo.bar.cls
// Assuming stored with name of clsField 

Field[] myClassObjectFields = clsField.getType().getDeclaredFields();

for (Field f : myClassObjectFields) {

    String fieldValue = f.get(primaryObject /* What to pass here? */); 
    // !!!! The above line Doesn't work since the primary Object doesn't have access to its child's fields

    System.out.println(fieldValue);

}





Reflection: Check if Type will fulfill new() constraint [duplicate]

This question already has an answer here:

I have a generic function with a new() constraint:

public void DoMagicStuff<T>() where t:new() {
  // do something
}

I call this function from within a loop over every type of an assembly:

foreach (var type in baseType.Assembly.GetTypes())
{
   MethodInfo method = GetMethod<LiteDbQueue>(q => q.DoMagicStuff<object>());
   CallGenericMethod(this, method, baseType, type, null);
}

This loop works fine if the Type inside the loop fits the new() constraint. But if that type does not have a new()-constructor (e.g. a static class) I receive an error

(Typename)', on 'Void DoMagicStuffT' violates the constraint of type 'T'.

I want to validate within the Loop if the Type fulfills the new() - constraint. So something like:

if (type.IsNewable()) { ... }

How can this be done?


Just for completion: The following methods are used to "cast" my types for the generic method. These work fine and are not really part of my problem:

public MethodInfo GetMethod<T>(Expression<Action<T>> expr) {
   return ((MethodCallExpression)expr.Body).Method.GetGenericMethodDefinition();
}

public object CallGenericMethod(object baseObject, MethodInfo method, Type baseType, Type entityType, object[] parameters)
{
   MethodInfo genericMethod = method.MakeGenericMethod(entityType);
   var paams = genericMethod.GetParameters();
   var retVal = genericMethod.Invoke(baseObject, parameters);
   return retVal;
}





How to create my own class type at runtime in java? There does not exist any Class definition

I have a problem definition where I need to create Class type and add fields, methods to it at runtime in Java. Once I have Class object of particular class type, I can create instance of that class.





IllegalCallableAccessException in kotlin-reflect

I use simple-xml in the Android app. Parsed member properties are debugged using Kotlin-reflect. Properties can be displayed correctly if @field: Element is used, but if @field: ElementList is used, An IllegalCallableAccessException occurs and debugging can not be displayed.

Please tell me what to do.

Error: Class kotlin.reflect.jvm.internal.FunctionCaller$FieldSetter I changed the version of gradle and tried invalidate Caches / Restart, but it does not improve.

gradle-wrapper.properties:gradle-5.1.1-all
build:gradle:3.4.1
kotlin version:1.3.21
simple-xml:2.7.1

sample.xml

<Test>
    <Res id="aaa">
        <Event/>
        <Type>Japan</Type>
    </Res>
    <Res id="bbb">
        <Event>manually</Event>
        <Type>Italy</Type>
    </Res>
    <Res id="ccc">
        <Event>manually</Event>
        <Type>America</Type>
    </Res>
</Test>

Test.kt

@Root(name = "Test", strict = false)
class Test{
    @field:ElementList(name = "Res", inline = true) var Res: ArrayList<Res>? = null
}

Res.kt

@Root(name = "Res", strict = false)
class Res {
    @field:Element(name = "Event", required = false) var Event:String? = null
    @field:Element(name = "Type", required = false) var Type:String? = null
}

MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
    ...some code ...
    ParseDebug.debug(Test::class, t)
}

ParseDebug.kt

class ParseDebug{
    companion object {
        fun <T : Any> debug(type: KClass<T>?, obj: T) {
            type?.memberProperties?.forEach { member ->
                member.get(obj)?.let { data ->
                    if (data is String || data is Int) {
                        // String or Integer
                        Log.d(type.simpleName, "${member.name}: $data")
                    } else {
                        debug(data.javaClass.kotlin, data)
                    }
                }
            }
        }
    }
}

It is an acquired error

 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.project/com.test.project.MainActivity}: kotlin.reflect.full.IllegalCallableAccessException: java.lang.IllegalAccessException: Class java.lang.Class<kotlin.reflect.jvm.internal.calls.CallerImpl$FieldGetter> cannot access transient  field java.lang.Object[] java.util.ArrayList.elementData of class java.lang.Class<java.util.ArrayList>
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3086)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3229)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:6981)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)





dimanche 2 juin 2019

Get Class properties and values using Typescript reflection

Say I have a class

Class A {}

And would like to iterate through Class A properties (checking for null values) only knowing that Class A will have properties but might vary in property names and number of properties (e.g.)

Class A {
  A: string;
  B: string;
} 

or

Class A {
  B: string;
  C: string;
  D: string;
}

Is there a way I can iterate through Class A properties and check if the values are null?





samedi 1 juin 2019

Why get_class_methods() does not show all methods of a specific PDO driver?

I was trying to get all method for each PDO driver (I have all of them installed on my PC Windows).

But if I try, for example, using Postgres (pdo_pgsql):

var_dump(get_class_methods($pdo));

The result is:

array(17) { [0]=> string(11) "__construct" [1]=> string(7) "prepare" [2]=> string(16) "beginTransaction" [3]=> string(6) "commit" [4]=> string(8) "rollBack" [5]=> string(13) "inTransaction" [6]=> string(12) "setAttribute" [7]=> string(4) "exec" [8]=> string(5) "query" [9]=> string(12) "lastInsertId" [10]=> string(9) "errorCode" [11]=> string(9) "errorInfo" [12]=> string(12) "getAttribute" [13]=> string(5) "quote" [14]=> string(8) "__wakeup" [15]=> string(7) "__sleep" [16]=> string(19) "getAvailableDrivers" } 

But this list is incomplete because PDO Postgres includes methods like:

$pdo->pgsqlCopyToArray('my_table');

Is there a way to get all methods and not only the PDO defaults only?

Thanks in advance, Celso

Edit:

I've tried Reflection too, and the result is incomplete like get_class_methods():

var_dump(array_column((new ReflectionClass($pdo))->getMethods(), 'name'));

The result:

array(17) { [0]=> string(11) "__construct" [1]=> string(7) "prepare" [2]=> string(16) "beginTransaction" [3]=> string(6) "commit" [4]=> string(8) "rollBack" [5]=> string(13) "inTransaction" [6]=> string(12) "setAttribute" [7]=> string(4) "exec" [8]=> string(5) "query" [9]=> string(12) "lastInsertId" [10]=> string(9) "errorCode" [11]=> string(9) "errorInfo" [12]=> string(12) "getAttribute" [13]=> string(5) "quote" [14]=> string(8) "__wakeup" [15]=> string(7) "__sleep" [16]=> string(19) "getAvailableDrivers" } 





Reflection: Applying type parameters of declaring class to fields

I have the below class structure:

class A<T> {
   B<T> b;
}

class B<T> {
   T t;
}

class StringConsumer {
   A<String> a;
}

class LongConsumer {
   A<Long> a;
}

Given that I have an instance of one of the consumer classes, is it possible to obtain the type parameter for consumer.a.b? I found that I am able to resolve the same if I declare a as StringA a; where class StringA extends A<String> using TypeTools