samedi 8 mai 2021

Why is the `Mirror.child.label` field not handling self-referential classes properly?

I am using reflection in Swift to write a generic object (Any) to dictionary in Swift; both for educational purposes and production purposes too.

The code works but one of my tests showed that for self-referential classes, it does not work properly.

When accessing the referenced member field whose type is same as the class, the Mirror.child.label field returns a value of some as the dictionary key , before accessing the member's variables.

A good example:

class Node{
  var next: Node!
  var val: Int = 0

init(_ val: Int){
self.val = val
}

}
  
 
let node = Node(4)
node.next = Node(5)
node.next.next = Node(6)


print("node.toDictionary: " , toDictionary(obj: node))

The output is:

node.toDictionary:  ["val": 4, "next": ["some": ["next": ["some": ["val": 6, "next": [:]]], "val": 5]]]

Needless to say, the expected output is:

["next": ["next": ["val": 6],"val": 5],"val": 4]

The minimal code for toDictionary which produces this error is:

func toDictionary(obj: Any) -> [String:Any] {
    var dict = [String:Any]()
    let otherObj = Mirror(reflecting: obj)
    for child in otherObj.children {
        if let key = child.label {
          
            if child.value is String || child.value is Character || child.value is Bool
                || child.value is Int  || child.value is Int8  || child.value is Int16  || child.value is Int32 || child.value is Int64
                || child.value is UInt  || child.value is UInt8  || child.value is UInt16  || child.value is UInt32 || child.value is UInt64
                || child.value is Float  || child.value is Float32 || child.value is Float64 || child.value is Double
            {
                dict[key] = child.value
            }
            else if child.value is [String] || child.value is [Character] || child.value is [Bool]
                || child.value is [Int]  || child.value is [Int8]  || child.value is [Int16]  || child.value is [Int32] || child.value is [Int64]
                || child.value is [UInt]  || child.value is [UInt8]  || child.value is [UInt16]  || child.value is [UInt32] || child.value is [UInt64]
                || child.value is [Float]  || child.value is [Float32] || child.value is [Float64] || child.value is [Double]{
                
                let array = child.value as! [Any]
                
                
                dict[key] = array
                
                
            }else if child.value is [Any]{
                 let array = child.value as! [Any]
                 var arr:[Any] = []
                for any in array{
                    arr.append(toDictionary(obj: any))
                }
                dict[key] = arr
            }
            else{
                dict[key] = toDictionary(obj: child.value)
            }
            
        }
    }
    return dict
}

Why is the Mirror.child.label field not handling self-referential classes properly?





vendredi 7 mai 2021

Java reflection arrays of List

I'm trying to implement a class that can initialize values into an object of any class. The initialization of simple structures is already functional, but I got stuck trying to initialize the array of Lists (List<String>[]).

Is there any way to find out the ParameterizedType and not just the Class of the array by getComponentType()?

Creation of array:

if (cls.isArray()) {
  Class<?> c = cls.getComponentType();
  if (!c.isPrimitive()) {
    Array array = new Array(c, this.sizeArrays);

    for (int i = 0; i < this.sizeArrays; i++) {
      array.set(i, init(c, c, this.sizeArrays, this.sizeCollection, this.recursionCount, this.values, this.ignoredClass));
    }

    return array.getArray();
  }

Class Array:

class Array<E> {
private final E[] objArray;
public final int length;

public Array(
    Class<E> dataType,
    int length
) {
  //noinspection unchecked
  this.objArray = (E[]) java.lang.reflect.Array.newInstance(dataType, length);
  this.length = length;
}

void set(
    int i,
    E e
) {
  objArray[i] = e;
}

E[] getArray() {
  return objArray;
}

}

Creating List:

if (Collection.class.isAssignableFrom(cls)) {
  ParameterizedType t = ((ParameterizedType) cls.getGenericSuperclass());
  if (type instanceof ParameterizedType) {
    ParameterizedType pt = (ParameterizedType) type;
    Collection collection;
    if (List.class.isAssignableFrom(cls)) {
      collection = new ArrayList(this.sizeCollection);
    } else if (Set.class.isAssignableFrom(cls)) {
      collection = new HashSet(this.sizeCollection);
    } else if (Queue.class.isAssignableFrom(cls)) {
      collection = new LinkedList();
    } else {
      collection = new ArrayList(this.sizeCollection);
    }
    for (int i = 0; i < this.sizeCollection; i++) {
      collection.add(init((Class<?>) pt.getActualTypeArguments()[0], pt.getActualTypeArguments()[0], this.sizeArrays, this.sizeCollection, this.recursionCount, this.values, this.ignoredClass));
    }

    return collection;
  }
}




jeudi 6 mai 2021

Get value of optional types when retrieving value of record fields in F#

I have a type defined as follows:

type Employee = {
    Id:    Guid
    Name:  string
    Phone: string
    Email: Option<string>
}

and an instance of this type:

let emp = {
    Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
    Name = "A"
    Phone = "B"
    Email = Some "E"
}

I want to extract the field names and values from this record type using reflection like the following:

let getFieldValueMappingOfARecordType (data: 'T) : seq<string * obj> =
    let fieldValueMapping =
        data.GetType()
        |> FSharpType.GetRecordFields
        |> Seq.map (
            fun propertyInfo ->

                    (propertyInfo.Name, data |> propertyInfo.GetValue)
        )
    fieldValueMapping

Then invoking the above function with the instance of employee type

let mapping = getFieldValueMappingOfARecordType emp
            |> Seq.toList

gives us:

val mapping : (string * obj) list =
  [("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
   ("Email", Some "E")]

So far it's working well with non-optional type. But in case of optional types, it's returning the value of the field as either Some value or None. What I would like to do is to get the value when the field has Some value or make it null when it's None.

Essentially like the follwing:

val mapping : (string * obj) list =
  [("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
   ("Email", "E")]

Or if the employee instance is like the following:

let emp = {
    Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
    Name = "A"
    Phone = "B"
    Email = None
}

Then,

val mapping : (string * obj) list =
  [("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
   ("Email", null)]

This is what I have so far (non-working code):

open System
open Microsoft.FSharp.Reflection
open System.Reflection

type Employee = {
    Id:    Guid
    Name:  string
    Phone: string
    Email: Option<string>
}

let emp = {
    Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
    Name = "A"
    Phone = "B"
    Email = Some "E"
}

let getSomeOrNull (t: Type) (o: obj) =
    let opt = typedefof<option<_>>.MakeGenericType [| t |]
    match (o :?> opt) with
    | Some s ->
        s
    | None ->
        null

let getValues (data: 'T) =
    let values =
        data.GetType()
        |> FSharpType.GetRecordFields
        |> Array.map (
            fun propertyInfo ->
                let value =
                    data |> propertyInfo.GetValue

                let isOption =
                    propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() = typedefof<Option<_>>

                match isOption with
                | true ->
                    (propertyInfo.Name, (getSomeOrNull propertyInfo.PropertyType value))
                | false ->
                    (propertyInfo.Name, value)
        )
    values

getValues emp
|> printfn "%A"




How do I specify Binding Flags to capture fields of type int? [duplicate]

I am trying to figure out why the following code does not retrieve fields of type int?

     private static List<FieldInfo> GetRelevantFields(Type type)
    {
        var myObjectFields = type.GetFields(
            BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
        var nonKeyFields = myObjectFields.ToList();
        var fields = new List<FieldInfo>();
        foreach (var fi in from fi in nonKeyFields
            let colType = ColType(fi)
            where colType != DBColumnType.Unknown // objects and nullable columns will be missed
            select fi) fields.Add(fi);
        return fields;
    }

For example if I use

public class MyBusinessObject 
{ 
   public int? LookupId { get; set; } // this binding will not be retreived
   public int  Lookup2Id {get;set;} // this binding will be retreived
}

How do I get it to?

Looking at the decompiled code

Binding Flags





Check if Property in Typescript Object is Optional

I'm trying to create dynamic form validation based on the interface of a model.

My test model interface is as so:

IRole {
   id: string;
   name: string;
   description?: string;
}

I have two instances of Role

Without description:

const role1: IRole = {
   grants: ['admin:*'];
   name: 'Admin'; 
}

With description:

const role2: IRole = {
   grants: ['owner:*'];
   name: 'User';
   desciption: 'Average Joe';
}

Required fields for a form would be:

[grants, name]

Option field would be:

[description]

The interface has the details I need. This doesn't seem possible to do but wanted to check with others before I abandon this approach.





Using Reflection on Type T to create Expression

I'm currently exploring the viability to encapsulate some logic that would typically be iterative. Using a 3rd party library it has a generic Html Helper method that allows you to map properties from a Generic T class to a table component. Typically you'd have to write something to the effect of:

HtmlHelper.GenerateTable<ClassName>
.configure(tableDefinition =>{
  // Adding each property you want to render here
  tableDefinition.add(myClassRef => myClassRef.propertyA);
  tableDefinition.add(myClassRef => myClassRef.propertyB);
})

I'm exploring the idea of adding attributes to properties such as a standard Display attribute and then using reflection, adding that property to the container. The add method only accepts an argument of type Expression<Func<T, TValue>>. With my current understanding of reflection I know I can property identify properties that would be applicable by looping through PropertyInfo and checking for the attribute I want using GetCustomAttribute.

What I'm stumped on is if it's possible using reflection to supply the argument type that the add method expects?

I'll throw the helper method logic I've started using so far. My assumption is that this is leading me towards Expression and Lambda classes, but I haven't been able to flesh out anything that works since I don't technically have a TValue.


var t = typeof(T);
List<PropertyInfo> properties = t.GetProperties().ToList();
foreach(var prop in properties)
{
    var attr = (DisplayAttribute[])prop.GetCustomAttributes(typeof(DisplayAttribute), false);
    if (attr.Length > 0)
    {
        // TODO: Call add with expression?
    }
}




sonar dynamic class loading issue

How could I fix sonnar issue delete dynamic class loading

protected Class registerAndLoadClass(String className) throws ClassNotFoundException {
        Class definedClass = classLoader.loadClass(className);
        addDefinedClass(definedClass, true, null);
        return definedClass;
    }

I tried

 protected Class registerAndLoadClass(String className) throws ClassNotFoundException {
        Class definedClass = null;
        try {
             definedClass = (Class) classLoader.getClass()
                    .getDeclaredMethod("loadClass", String.class, boolean.class)
                    .invoke(null, className);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        addDefinedClass(definedClass, true, null);
        return definedClass;
    }

But it send NPE, when I'm trying to use it.