vendredi 27 octobre 2023

MethodHandle Lookup Issues

I've recently needed to make a relatively simple events system. (Id -> Consumer) This would be able to subscribe a Method based off annotation. Then I remembered that Java isn't C# and attempted to look for a way to accomplish this. After many similar threads, I came across this GitHub Gist, and attempted to implement it. I did so successfully, however did not realize early enough that the MethodHandles.lookup() method is location specific and only applies to the class that calls it.

ConsumerFactory

public class ConsumerFactory {
    private final Method consumerMethod;
    private final MethodType consumerMethodType;

    private final Map<Method, Consumer<?>> methodCache = new HashMap<>();

    public ConsumerFactory() {
        consumerMethod = findLambdaMethod(Consumer.class);
        consumerMethodType = MethodType.methodType(consumerMethod.getReturnType(), consumerMethod.getParameterTypes());
    }

    public <T, L> Consumer<T> createConsumer(L instance, Method implMethod) throws Throwable {
        Consumer<T> cached = (Consumer<T>) methodCache.get(implMethod);
        if(cached==null) {
            Class<?> implType = implMethod.getDeclaringClass();

            MethodHandles.Lookup lookup = MethodHandles.lookup().in(implType);
            MethodType implMethodType = MethodType.methodType(implMethod.getReturnType(), implMethod.getParameterTypes());
            MethodHandle implMethodHandle = lookup.findVirtual(implType, implMethod.getName(), implMethodType);

            MethodType invokedMethodType = MethodType.methodType(Consumer.class, implType);

            CallSite metaFactory = LambdaMetafactory.metafactory(
                    lookup,
                    consumerMethod.getName(), invokedMethodType, consumerMethodType,
                    implMethodHandle, implMethodType);

            MethodHandle factory = metaFactory.getTarget();
            Consumer<T> consumer = (Consumer<T>) factory.invoke(instance);
            methodCache.put(implMethod, consumer);
            return consumer;
        }
        return cached;
    }

    private Method findLambdaMethod(Class<?> type) {
        if (!type.isInterface()) {
            throw new IllegalArgumentException("This must be interface: " + type);
        }
        Method[] methods = getAllMethods(type);
        if (methods.length == 0) {
            throw new IllegalArgumentException("No methods in: " + type.getName());
        }
        Method targetMethod = null;
        for (Method method : methods) {
            if (isInterfaceMethod(method)) {
                if (targetMethod != null) {
                    throw new IllegalArgumentException("This isn't functional interface: " + type.getName());
                }
                targetMethod = method;
            }
        }
        if (targetMethod == null) {
            throw new IllegalArgumentException("No method in: " + type.getName());
        }
        return targetMethod;
    }
    private Method[] getAllMethods(Class<?> type) {
        LinkedList<Method> result = new LinkedList<>();
        Class<?> current = type;
        do {
            result.addAll(Arrays.asList(current.getMethods()));
        } while ((current = current.getSuperclass()) != null);
        return result.toArray(new Method[0]);
    }
    private boolean isInterfaceMethod(Method method) {
        return !method.isDefault() && Modifier.isAbstract(method.getModifiers());
    }
}

Is their anything I could do to still have this sort of idea function? Ideally end up as something like Map<String, Consumer<Event>>. I was considering forcefully creating a Lookup class, but I'm not sure if that would be the best idea.

Thank you all for the help!





Get the type name of a Dictionary with generics in C#

Is there an easy or elegant way to get the type name of a Dictionary with the generic types in C#?

Currently I have this code works:

if (property.PropertyType.Name == "Dictionary`2")
{
    Type[] arguments = property.PropertyType.GetGenericArguments();
    Type keyType = arguments[0];
    Type valueType = arguments[1];
    properties[property.Name] = $"Dictionary<{keyType.Name},{valueType.Name}>";
}

I was wondering whether there is more easy way of achieving this formatted string that I'm looking for, like: "Dictionary<type, type>"





mercredi 25 octobre 2023

Blazor validate custom editor control bound to property by name

In my Blazor server app, I created a CustomEdit control to edit DateTime properties of an object by name:

NOTE this is an illustration - using an existing DateTime editor is not the point here, the point is I am binding to a property by its name!

@typeparam TItem;
@inherits ComponentBase;  
@if (Context != null) {
  <InputText @bind-Value="@DateStr" />
  <ValidationMessage For="@(() => DateStr)" />
}
@code {
  [Parameter]
  public TItem Context { get; set; }

  [Parameter]
  public string BoundPropertyName { get; set; }

  [Parameter]
  public string DateFormat { get; set; } = "dd.MM.yyyy";

  protected override void OnParametersSet() {
    if (_pInfo == null) {
      _pInfo = typeof(TItem).GetProperty(BoundPropertyName);
    }
    base.OnParametersSet();
  }
  PropertyInfo _pInfo;

  bool isValid(DateTime result) {
    if (_pInfo == null || Context == null) {
      return false;
    }
    // --- validation
    var valContext = new ValidationContext(Context) { MemberName = BoundPropertyName };
    var validationResults = new List<ValidationResult>();
    return Validator.TryValidateProperty(result, valContext, validationResults);
  }
  string DateStr {
    get => _pInfo != null && Context != null ? ((DateTime)_pInfo.GetValue(Context)).ToString(DateFormat) : string.Empty;
    set {
      DateTime result;
      if (DateTime.TryParseExact(value, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out result) && isValid(result)) {
        _pInfo.SetValue(Context, result);
      }
    }
  }
}

I created an edit form bound to a PersonData model with a birthday as follows within the edit form:

<CustomEdit TItem="PersonData" BoundPropertyName="@nameof(PersonData.BirthDate)" Context="@model" />

Now, I see the validation triggers as expected, returns false for an empty string for example, but my validation message is not showing and the editor box appears as valid (green) as it shouldn't (PersonDate.BirthDate is flagged as [Required] and also with a custom ValidDateAttribute that has some internal logic). Why is the message not showing?

As a side-note: if I use an existing DateTime editor and directly @bind-Value="@context.Birthday", validation works perfectly and shows the validation errors I want to see...





dimanche 22 octobre 2023

C++ how to get the first and the last element in an std::vector by its base memory address

To me, a vector layout looks something like this:

struct MyViewOnHowVectorLooksLike
{
public:
   int* _first, * _last, * _end;
};

Known Parameters:

  1. Address of the std::vector<Type> object
  2. size of the <Type>

Questions:

  1. Find the address of the first element and the last element in the vector

Is there any way to access the first and last elements in a std::vector by its base memory address, which is &Test in the above test case, not by calling any build-in method of the std::vector function eg [0], .front(), etc; (The reason why I'm doing this is to have a static reflection system which could output the content of any given written vector type)

struct FTestData {
    int data;
};

class TestClass {
public:
    // test array
    std::vector<FTestData> testArray;

    TestClass(){}
};

// TEST CASE
FTestData testCon1 = FTestData();
testCon1.data = 111;
FTestData testCon2 = FTestData();
testCon2.data = 222;

TestClass Test = TestClass();
Test.testArray.push_back(testCon1);
Test.testArray.push_back(testCon2);

std::vector<FTestData>* TestData = (std::vector<FTestData>*)((size_t)&Test);
size_t ptr = (size_t)TestData;
FTestData& TestElement1 = (*TestData)[0];
size_t realFirstElementAddress = (size_t)&TestElement1;

// try to get the address of the first element in the vector but it  gives me the wrong address
size_t CustomFirstElementAddress = (*(size_t*)(ptr));

// expecting those two to be the same but it wasnt
assert(realFirstElementAddress == CustomFirstElementAddress);

I thought the _First and _Last are right next to the base address, but it keeps outputting the wrong results.

AddOn: The real problem I am trying to solve is to have a detail panel with my own reflection system, which could allow me do something like this. It works for most common types, and nested class.

{
    if (field.Type == "int") {
        int location[1];
        auto& value = *(int*)((size_t)&Component + Offset + field.Offset);
        memcpy(location, &value, sizeof(location));
        if (ImGui::DragInt(fieldName.c_str(), location, 0.1f, 0.0f, 0.0f, "%.1f"))
        {
            memcpy(&value, location, sizeof(location));
        }
    }
    else if (field.Type == "std::string") {
        char buffer[256];
        memset(buffer, 0, sizeof(buffer));
        auto& value = *(std::string*)((size_t)&Component+ Offset + field.Offset);
        strcpy(buffer, value.c_str());
        if (ImGui::InputText(fieldName.c_str(), buffer, sizeof(buffer))) {
            value = std::string(buffer);
        }
    }
    else if (field.Type == "bool") {
        bool location[1];
        auto& value = *(bool*)((size_t)&Component + Offset + field.Offset);
        memcpy(location, &value, sizeof(location));
        if (ImGui::Checkbox(fieldName.c_str(), location)) {
            memcpy(&value, location, sizeof(location));
        }
    }
    else if (field.Type == "float") {
        float location[1];
        auto& value = *(float*)((size_t)&Component + Offset + field.Offset);
        memcpy(location, &value, sizeof(location));
        if (ImGui::DragFloat(fieldName.c_str(), location, 0.1f, 0.0f, 0.0f, "%.1f"))
        {
            memcpy(&value, location, sizeof(location));
        }
    }
}




wierd class cast using dynamic proxy and java17 - java modules exception

I have trying to make a simple dynamic proxy example work without success. I assume I am doing something wrong but reading some java modules tuts and proxy tuts did not help me understand... the code is super basic with an interface, its implementation, an invocatgion handler and the class with the main method that runs the example:

package com.example.proxy;

public interface Foo {
    public String foo(String s);
}

package com.example.proxy;

    public class FooImpl implements Foo{
    
        @Override
        public String foo(String str) {
            return str;
        }
        
    }

package com.example.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class FooProxy implements InvocationHandler{
    Foo foo;
    public FooProxy(Foo s){
        this.foo = s;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("%#$%#5^$@5^$@5^   PROXY");
        return ("[proxied] "+method.invoke(this.foo, args));
    }
    
}

package com.example.proxy;


import java.lang.reflect.Proxy;


public class MainTest {

    public static void main(String [] args){
        Foo o = (Foo)Proxy.newProxyInstance(Foo.class.getClassLoader(), Foo.class.getInterfaces(), new FooProxy(new FooImpl() ));

    }
}

running maintest yeilds:

Exception in thread "main" java.lang.ClassCastException: class jdk.proxy1.$Proxy0 cannot be cast to class com.example.proxy.Foo (jdk.proxy1.$Proxy0 is in module jdk.proxy1 of loader 'app'; com.example.proxy.Foo is in unnamed module of loader 'app')
    at com.example.proxy.MainTest.main(MainTest.java:10)

I tried exposing com.example.proxy in module-info.java explicitly, trying some opens etc but nothing helped so I assume I do not get something. can anyone help point me in the right direction thanks!





Get field of struct pointer if not nil, otherwise default value

I'm looking for a function that would reduce the redundancy in accessing a member of a struct pointer in Go. It should perform the member access if the pointer is not nil, or return a default value otherwise. It should be functionally equivalent to:

var ptr *MyStruct
var result any
if ptr != nil {
    result = ptr.MyField
} else {
    result = sql.NullFloat64{}
}

In principle, this pattern comes from the orElse of optionals in many other languages. The use case is to extract a field from a nested protobuf message and stuff it into a SQL query. The resulting function looks like the following:

func GetFieldOrElse(v any, fn string, or any) any {
    segments := strings.Split(fn, ".")
    r := reflect.ValueOf(v)
    for _, field := range segments {
        if r.IsNil() {
            return or
        }
        r = reflect.Indirect(r).FieldByName(field)
    }
    return r.Interface()
}

// pi is a protobuf message and ExtraParams is a nested message inside `pi`
GetFieldOrElse(pi.ExtraParams, "Make", sql.NullString{})
GetFieldOrElse(pi.ExtraParams, "Model", sql.NullString{})
GetFieldOrElse(pi.ExtraParams, "LensModel", sql.NullString{})
GetFieldOrElse(pi.ExtraParams, "Aperture.Numerator", sql.NullInt64{})
GetFieldOrElse(pi.ExtraParams, "Aperture.Denominator", sql.NullInt64{})

I tried to look for a compile-time solution (i.e. without reflection) but failed. Is this the idiomatic way of achieving this goal?





vendredi 20 octobre 2023

Title: Why does Spring Data JDBC use reflection in PersistentPropertyAccessor, and could code generation improve performance?

Question: I'm currently working with Spring Data JDBC, and I've noticed that PersistentPropertyAccessor relies on reflection to access and manipulate properties. I understand that reflection can be slow, and I'm wondering why this choice was made.

  1. What are the reasons behind using reflection in PersistentPropertyAccessor in Spring Data JDBC?

  2. Have there been any performance considerations taken into account when choosing reflection as the method for property access?

  3. Could using code generation tools like MapStruct provide a performance improvement in this context, and are there any trade-offs to consider?

    I'm interested in understanding the design decisions and potential performance enhancements related to this specific aspect of Spring Data JDBC. Any insights or best practices in this area would be greatly appreciated.