jeudi 3 mars 2022

2D Laser or Projectile reflection in Pygame

I am stuck on a problem and am actually confused in implementing the logic of that thing.Actually i want to bounce the (say line in pygame) in an enclosed rectangle.By considering the max no of bounces that the line will bounce off and the whole movement of the laser or line will be controlled by holding LeftMouse button and moving around and the angles of line should move! Here is the pic related to that from a unity project! Laser Reflection

Any help will be greatly appreciated! Thankyou





How to pass generics in reflecive methods as argument (i.e method.invoke(currClass, GenericClass))

What I am needing is to use reflections to get a class's methods. The method I want to use has a complex type as a parameter, that is unknown at runtime. Using reflections I want to create another Class object that is of this paramter's type. Then call the original class's method with this class object as an argument.

It seems that java does not like me using generics in this fashion. Since it is expecting a argument of a complex type rather than a generic it complains about IllegalArgumentException.

I have tried to simply this algorithm to its core for the sake of making this problem as simple as possible. Assume that a Message may have an unknown number of Complex types and each of those have an unknown number of Complex types within them as well . What I am wanting is to create a method that:

  1. takes in Class object.
  2. Inspects its contents for setMethods.
  3. If current setMethod has a non-primitive as an argument call this method again with the that class type.
  4. When it finds a primitive type use that class's setMethod return this class object.
  5. When we are done inspecting this current Class attempt to pass the returned class into the current class's setMethod that is expecting a complex type.

Step 5 is where I run into issues. Since our method, "Message.setTransactionId" expects an argument of type, "TransactionId", but instead is getting a type Object, or type Class instead I am getting the error, "java.lang.IllegalArgumentException: argument type mismatch"

Problem in simplest form:

    Object nextClass = TransactionId.class;
    Object newClass = Message.class;
    Method[] currentMethods = newClass.getMethods();

    currentMethods[0].invoke(newClass,nextClass);

Little bit more detail:

    public class Message {
        
        private TransactionId myTranactionId;

        public void setTransactionId(TransactionId transactionId){
            myTranactionId = transactionId;
        }
    }

    public class TransactionId{

        private int value;    

        private setValue(int value){
            this.value = value
        }
    }

    public class TestReflections{

        public TestReflections(){

            Class currentTestClass = Message.class;
            parseClass(currentTestClass);
        }

        public class parseClass(Class className){
            int valueToBeAdded = 1;
            Method[] currentMethods = className.getMethods();

            Object nextClass = null;
            Object newClass = className.newInstance();

            for(Method method: currentMethods){
                if(method.getName().startsWith("set")){
                    Class[] methodParams = method.getParameterTypes();
                    if(methodParams[0].isPrimitive()){
                        method.invoke(newClass, valueToBeAdded)
                        return className;
                    }else{
                        nextClass = parseClass(methodParams[0]);
                    }        
                method.invoke(newClass, nextClass);
                return className;
                }
            }
            return className;

        }


    }




Intermittent TypeLoadException when calling Assembly.GetType - Method in type from assembly does not have an implementation (ONLY SOMETIMES)

In my project, there is an abstract base class with an abstract method. We generate implementations based on a schema and later load these by reflection with Assembly.LoadFrom and then call Assembly.GetType to get a concrete implementation of an interface which is defined in yet another DLL.

The structure of the different projects (DLL files):

  1. Schema - Containing type definition
  2. Base - Has the base class shared by all generated implementations
  3. Generated - A generated type that implements the abstract base class from Base and the interface from Schema.
public interface IExample 
{
   //Some methods here, irrelevant to the problem
}
public abstract Base 
{
    protected abstract void SomeMethod(SomeType someArg); //This method is the method the exception specifies, but I suspect it's only because it's the first one in the file.

    //More methods like the above, and some non-abstract/virtual methods too
}
public class Generated : Base, IExample
{
    protected override void SomeMethod(SomeType someArg)
    {  
        //Some implementation here
    }
    
    //More content here, not all of it being from either the interface or the Base type

}
var asm = Assembly.LoadFrom(path);
asm.GetType("Generated"); //This is where it fails

This worked fine until the Base project was updated in an unrelated area and its version advanced.

The generated implementation is being requested by the interface type it implements. (Generics are involved in the type definition, not sure if that's really relevant)

Now normally this would be a simple case of "Oh you just need to re-compile it and include it again" but the exciting part is that this only sometimes fails!

Roughly half the time, it just works. The other half, it throws the TypeLoadException arguing the method doesn't have an implementation. Normally I'd expect it to always fail, but that's not the case.

Of course, including the newly compiled Generated DLL avoids this entirely. But I'm looking to be able to update both the Schema and Base projects without requiring the whole thing. (It's for 'service pack' style software updates only containing the relevant files)

Just to be clear, none of the involved types were modified. No "Oh I just added an optional argument to a method so it's the same method" mistakes.

The only changes are in other parts of the files. Base is in a big DLL with lots of unrelated utility in it. Base, IExample, and the resulting Generated are still exactly the same. If it was some version resolution causing havoc, I'd expect problems.

This is sadly not a simple small project I could pack up into a reproducible example, but a rather complicated program with many layers and patterns. I'm not sure I could reproduce this if I tried, I'm relying on it failing when the program starts loading things and calling code. (The relevant reflection code that creates an instance of Generated)

The exception message looks like this: (names changed to match example code, and yes its assembly version is 0.0.0.0)

System.TypeLoadException: Method 'SomeMethod' in type 'SomeNameSpace.Generated' from assembly 'SomeNameSpace.Generated, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
   at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type)
   at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   at SomeMoreOfOurOwn.CallingTheReflection.AndFailing(Factory factory)

As mentioned, this is a case where trying the same thing and hoping for different results works, because this issue doesn't happen half the time. (And not due to the code not being called, the codebase is built on this pattern for everything)
The only predictable thing is that it always fails on the same thing, but I think that's just because it's deterministically doing that one thing first amongst all of the non-updated generated files.





Dealing with derived properties with same name as in base class using reflection

I will try to explain my best, but it is a tricky one to explain.

I am having a problem using reflection when a derived object redefines a property already in a base class.

Let's consider the following classes to start with:

// The base class
namespace MyNamesapce
{
    [DataContract]
    public abstract class MyClassBase: IMyClassBase
    {
        [JsonConstructor]
        public MyClassBase()
        {

        }

        public string Info { get; set; }
        public string Unit { get; set; }
        public string Name { get; set; }
    }
}

// MyClassArray is most of the time used
namespace MyNamesapce
{
    [DataContract]
    public class MyClassArray<TType> : MyClassBase, IMyClassArray<TType>
    {
        public MyClassArray()
        {
        }

        [JsonConstructor]
        public MyClassArray(IEnumerable<TType> value, TType minValue, TType maxValue)
        {
            MinValue = minValue;
            MaxValue = maxValue;
            Value = value;
        }

        [DataMember]
        public IEnumerable<TType> Value { get; set;  }

        [DataMember]
        public TType MinValue { get; set; }

        [DataMember]
        public TType MaxValue { get; set; }
    }
}

// In some rare cases we need 2D arrays
namespace MyNamesapce
{
    [DataContract]
    public class MyClass2DArray<TType> : MyClassArray<TType>, IMyClass2DArray<TType>
    {
        private int[] _arraySize { get; set; }

        public MyClass2DArray()
        {
        }

        [JsonConstructor]
        public MyClass2DArray(TType[][] value, TType minValue, TType maxValue)
        {
            MinValue = minValue;
            MaxValue = maxValue;

            _arraySize = new int[2] { value.Count(), value[0].Length };

            Value = value;
        }

        [DataMember]
        public new TType[][] Value
        {
            get
            {
                TType[][] array2D = new TType[_arraySize[0]][];

                // Reconstruct the 2D array
                TType[] tmpArray;
                int startIdx = 0;
                for (int numArrays = 0; numArrays < _arraySize[0]; numArrays++)
                {
                    tmpArray = new TType[_arraySize[1]];
                    Array.Copy(base.Value.ToArray(), startIdx, tmpArray, 0, _arraySize[1]);
                    startIdx += _arraySize[1];

                    array2D[numArrays] = tmpArray;
                }

                return array2D;
            }
            set
            {
                // Should not be able to set _value to null
                if (value == null)
                    return;

                base.Value = value.SelectMany(v => v).ToArray();
            }
        }
    }
}

I now need to get all the properties from all instances of MyClassArray and MyClassArray2D. You will say, there are plenty of threads discussing that very point, just use "GetType().GetProperties()" for the former and use "GetType().GetProperty(..., BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)" for the latter.
The problem is that I do not know in advance which class is being processed. In my system when deserialising a Json, instances of both MyClassArray and MyClassArray2D have to be reconstructed, which is done using the following setter:

public static void SetProperty(this Object obj, string propName, Object value)
{
    PropertyInfo info = null;
    object[] indexer = null;

    string[] nameParts = propName.Split('.');

    if (obj == null) { return; }

    var props = obj.GetType().GetProperties();

    for (int idx = 0; idx < nameParts.Count() - 1; idx++)
    {
        try
        {
            indexer = null;

            // Try to access normal property
            info = obj.GetType().GetProperty(nameParts[idx]);

            if (info == null)
                continue;

            obj = info.GetValue(obj, indexer);
        }
        catch
        {
            info = null;
            indexer = null;
        }
    }

    if (obj != null)
    {

        // !!! Note that here, using declare only will only work when using derived classes
        PropertyInfo propertyToSet = obj.GetType().GetProperty(nameParts.Last(), BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); // | BindingFlags.DeclaredOnly);
        propertyToSet?.SetValue(obj, value);

    }
    else
    {
        throw new SystemException($"Could not find the property {propName}");
    }

}

As you can see an object is passed in to SetProperty() (that can be of any type).
When it is of type MyClassArray, there are no problems, but if it is of type MyClassArray2D it does not quite work as the latter redefines "Value", which will break the logic as 2 properties called value will exist. I need a way to detect that.
The first loop seems to do the right thing. "obj = info.GetValue(obj, indexer);" will return "obj" containing all the versions of "Value". The problem is in the next part of SetProperty().
How can I detect when more than one "Value" property is in "obj"? And how to always pick the derived version of "Value"?
Also if I just use "BindingFlags.DeclaredOnly" as done here in my code snipet, properties from the base class get lost/disappear, which is undesirable.
Is there maybe a way to return in "obj" all the properties without the duplicates coming from the base class? Or some kind of property filter maybe?





mercredi 2 mars 2022

Create Collection of type Class

Im trying to write a function that given a class it will build an object of that type (using reflection). Its working so far but im having trouble with Collections as members.

public static <T> T object(Class<T> type) throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException {

            T object = getNullInstanceOf(type);

            List<Field> fields = Arrays.asList(object.getClass().getDeclaredFields());

            for (Field f : fields) {
                f.setAccessible(true);
                if (Modifier.isFinal(f.getModifiers())) {
                    continue;
                }
                try {
                    Object fieldValue = f.get(object);
                    if (f.getType().equals(CharSequence.class) || f.getType().equals(String.class)) {
                        f.set(object, f.getName());
                    } else if (f.getType().equals(Integer.TYPE)) {
                        f.set(object, 1);
                    } else if (f.getType().equals(Double.TYPE)) {
                        f.set(object, 2.0);
                    } else if (f.getType().equals(Long.TYPE)) {
                        f.set(object, 3L);
                    } else if (isClassCollection(f.getType())) {
                        f.set(object,
                                ((Collection) getNullInstanceOf(f.getType())) // this throws a "No Such Method Exists" Exception
                                    .add(object(f.getGenericType().getClass()))); 
                    } else if (!(f.getType().equals(type))) {
                        f.set(object, object(f.getType()));
                    } else {
                        return null;
                    }
                } catch (Exception e) {
                    System.err.println("Could not access:" + f.getName());
                    continue;
                }
            }
            return object;
        }

        public static boolean isClassCollection(Class<?> c) {
            return Collection.class.isAssignableFrom(c)
                    || Map.class.isAssignableFrom(c);
        }

        private static <T> T getNullInstanceOf(Class<T> type) throws InvocationTargetException, InstantiationException,
                IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
            Class<?> clazz = Class.forName(type.getName());
            Constructor<?> ctor = clazz.getConstructor();
            return (T) ctor.newInstance();
        }
    }

The issue im having is that when I try to create an instance of the collection, whether it be a set, list, or map, those classes are abstract. Is there a way to just pick a random implementation or do I have to hardcode a concrete subclass for every abstract class?





mardi 1 mars 2022

How to check if slice interface elements have the same dynamic type?

I have the following structs and they follow this structure:

A is the interface, and B, C, D are all types with interface A.

I have a slice of variables args all with type with interface A, each of which can be B, C, D type specifically.

I'd like to write a for loop to judge if all variables in the slice fall into the same dynamic type.

I wrote the following code:

var existingTyp A
for i, d := range args {
 switch typ := d.(type) {
   case *B, *C, *D:
    if existingTyp == nil {
        existingTyp = typ
    } else {
        if typ != existingTyp {
            panic("error!")
        }
   }
}

How to revise the code to achieve what I want?





ObjectC-Why can't I get the properties correctly using the class_copyPropertyList function?

  • macOS 11.5.2
  • Xcode 13.2.1
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <iostream>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Class clazz = NSClassFromString(@"NSString");
        uint32_t count = 0;
        objc_property_t* properties = class_copyPropertyList(clazz, &count);
        for (uint32_t i = 0; i < count; i++){
            const char* name = property_getName(properties[i]);
            std::cout << name << std::endl;
        }
        free(properties);
    }
    return 0;
}

I will take some snippets of the output:

hash
superclass
description
debugDescription
hash
superclass
description
debugDescription
vertexID
sha224
NS_isSourceOver
hash
superclass
description
debugDescription
...

From the output, we can find that attributes such as hash, description, superclass, etc. will appear repeatedly several times, while some attributes (such as UTF8String) do not appear in the result list. How should I get the list of properties correctly? I would appreciate it.