lundi 3 août 2020

Kotlin reflection doesn't work when code obfuscation is enabled

I have this class

object Config {

    val type = Type
    val clazz = Class

    object Type {
        val type1 = "1"
        val type2 = "2"
        val type3 = "3"
    }

    object Class {
        val class1 = "1"
        val class2 = "2"
        val class3 = "3"
    }
}

I need to get all variables (type1, type2, type3, class1, class2, class3).

To do this I have this method:

fun getAll(instance: Any? = null, depth: Int = 0): List<String> {
        if (depth > 2) {
            return emptyList()
        }

        val result = mutableListOf<String>()
        val currentInstance = instance ?: this

        val properties = currentInstance.javaClass.kotlin.declaredMemberProperties.filter { it.visibility == KVisibility.PUBLIC }
        
        for (prop in properties) {
            prop.get(currentInstance)?.let {

                if (it is String) {
                    result.add(it)
                } else {
                    result.addAll(getAll(it, depth + 1))
                }
            }
        }

        return result
    }

It works fine if code obfuscation is disabled.

When I add:

minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

It doesn't work anymore.

I tried to add @Keep annotation or a similar proguard rule. It doesn't work.

Important note. type1, type2, type3, class1, class2, class3 are never used in the code.





dimanche 2 août 2020

Unexpected behavior when checking equality of property where value is modified in the getter [duplicate]

Given the following class:

public class Employee
{
    private string _birthday { get; set; }
    public string Birthday
    {
        get
        {
            if (DateTime.TryParse(_birthday, out DateTime dateOfBirth))
                return dateOfBirth.AddYears(2000 - dateOfBirth.Year).ToString("MMM dd yyyy");
            else
                return null;
        }
        set
        {
            _birthday = value;
        }
    }
}

And the following code:

static void Main()
{
    var obj1 = new Employee() { Birthday = "Aug 02 2000" };
    var obj2 = new Employee() { Birthday = "Aug 02 2000" };

    var propA = typeof(Employee).GetProperty("Birthday");

    object obj1_propA_object = propA.GetValue(obj1);
    object obj2_propA_object = propA.GetValue(obj2);
    dynamic obj1_propA_dynamic = propA.GetValue(obj1);
    dynamic obj2_propA_dynamic = propA.GetValue(obj2);

    if (obj1.Birthday == obj2.Birthday)
        Console.WriteLine("EQUALS");
    else
        Console.WriteLine("NOT EQUALS");
    // Writes EQUALS

    if (obj1_propA_object == obj2_propA_object)
        Console.WriteLine("EQUALS");
    else
        Console.WriteLine("NOT EQUALS");
    // Writes NOT EQUALS

    if (obj1_propA_dynamic == obj2_propA_dynamic)
        Console.WriteLine("EQUALS");
    else
        Console.WriteLine("NOT EQUALS");
    // Writes EQUALS    
}

I can't understand why the property values when treated as "objects" are not considered equal, but they are seen as equal when comparing them as strings or dynamic. It seems to have something to do with the fact that the values are modified in the getter, since if I change the getter to return just "_birthday" without modifying it the equality comparison as an object works.

I'm happy to use "dynamic" instead of "object", but I would simply like to understand why.





Dynamically (at Runtime) Calling The iterator Operator Function Of An Array

When attempting to dynamically (reflection) call the iterator function of an array type

    @Test
    fun test_x() {
        val array: Array<String> = arrayOf("A", "B")
        val f: KFunction<*> = array::class.memberFunctions.filter { it.name == "iterator" && it.isOperator }.first()
        KotlinReflectionUtils.functionJsonInfo(f).printJson()
        val result = f.call(array)
        println(result)
    }

KotlinReflectionUtils.functionJsonInfo(f).printJson() is a debug line with the following output

{
    "name" : "iterator",
    "returnType" : "kotlin.collections.Iterator<T>",
    "parameters" : [ {
        "index" : 0,
        "name" : null,
        "type" : {
            "toString()" : "kotlin.Array<T>",
            "classifier" : "class kotlin.Array"
        },
        "java_class" : "kotlin.reflect.jvm.internal.KParameterImpl",
        "optional?" : false,
        "vararg?" : false,
        "isValue?" : false
    } ],
    "instance_receiver_parameter" : {
        "index" : 0,
        "name" : null,
        "type" : {
            "toString()" : "kotlin.Array<T>",
            "classifier" : "class kotlin.Array"
        },
        "java_class" : "kotlin.reflect.jvm.internal.KParameterImpl",
        "optional?" : false,
        "vararg?" : false
    },
    "visibility" : "public",
    "external?" : false,
    "infix?" : false,
    "inline?" : false,
    "operator?" : true,
    "isFinal?" : true,
    "suspend?" : false
}

val result = f.call(array) throws the following exception

kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Could not compute caller for function: public final operator fun iterator(): kotlin.collections.Iterator defined in kotlin.Array[DeserializedSimpleFunctionDescriptor@1199fe66] (member = null)





Detect if PHP generator accepts send()?

Is it possible to somehow detect if a generator can accept any send() command? That is, if it has any line like this:

$gen = yield;

Use-case is when generators are used to factor out side-effects (as in redux-saga). If no expression depends on the result of any side-effect, all side-effects can be run concurrently (non-blocking IO).

Did not find any useful info in the reflection API: https://www.php.net/manual/en/class.reflectiongenerator.php





How get property value with reflection in C#

I have a date-time variable like this:

DateTime myDate=DateTime.Now; // result is like this: 8/2/2020 12:54:07 PM

and I want to get myDate variable like this

DateTime getOnlyDate=myDate.Date; 

and I want to get myDate.Date; with reflection how can I get Date property value with reflection? with reflection I do something like this:

PropertyInfo myDate = typeof(DateTime).GetProperty("Date");

but I don`t know how can I request myDate.Date; value with reflection. thanks in advance





samedi 1 août 2020

What is the advantage of lambda expressions over method variables?

I'm very new to lambda expressions, so please bear with me. Say I have an interface with a single abstract function:

public interface IAbsFunc {
    public abstract void absFunc(int x);
}

In this case, I can store a lambda expression in a variable:

public class Lambda {
    public static void main(String[] args) {
        IAbsFunc obj = (int x) -> System.out.println(x);
        obj.absFunc(3);
    }
}

If I'm understanding things right, this is like storing a method in a variable. However, this can already be done with java.lang.reflect:

public class Lambda {
    public static void main(String[] args) throws Exception {
        Method obj = PrintStream.class.getDeclaredMethod("println", int.class);
        obj.invoke(System.out, 3);
    }
}

Clearly I'm missing something here. In what situation would a lambda expression be preferable?





Create generic Linq extension Method to "sew" data by Key

I have a collection of courses (Id, name, status, instructor, etc) and another collection of Pricing (CourseId, Price).

I am trying to write a linq extension method to merge these two together, but my reflection is a bit rusty. What am I missing?

This is how I want to call it:

courses.SewData(pricing, p => p.Id, c => c.CourseId);

This is the method that is being called. Im having issues with the ToDictionary Line. Its not compiling. How can I create a dictionary with my existing expression

public static class DataExtension {
    public static IEnumerable<TParent> SewData<TParent, TChild>(this IList<TParent> parentCollection, IList<TChild> childCollection, Expression<Func<TParent, object>> parentProperty, Expression<Func<TChild, object>> childProperty) {

        var parentPropertyInfo = ReflectionHelper.GetProperty(parentProperty);
        var childPropertyInfo = ReflectionHelper.GetProperty(childProperty);

        var parentDict = parentCollection.ToDictionary(parentProperty, x => x); //need help here
        foreach (var child in childCollection) {
            var childId = childPropertyInfo.GetValue(child);
            var parentItem = parentDict[childId];
            
            //use reflection here to map properties by name
            

            
            yield return parentItem;
        }          
    }
}