How to get the type of a non generic IList

I have a situation (Deserializer) where I have the System.Type of something that I know inherits from IList. From this method, I need to give back an instance of this type and make sure it has x elements, all filled with the default value.

Simplified code:

Public Function GetIListInstance(theType as System.Type) as IList
    ...
End Function

When the IList is a simple array, the solution is also simple; the type name ends with []
Making the code:

Public Function GetIListInstance(theType as System.Type) as IList
    If theType.Name.EndsWith("[]") Then
      Return theType.InstantiateArray(3) //return an array with 3 empty elements
    Else
      //not an array
      ...
    End If
End Function

When the IList is something else, I can make an instance of it, and use the IList interface to add the 3 elements:

Public Function GetIListInstance(theType as System.Type) as IList
    If theType.Name.EndsWith("[]") Then
      Return theType.InstantiateArray(3) //return an array with 3 empty elements
    Else
      //not an array,  code for .Net: Activator.CreateInstance
      Dim MyList = TheType.Instantiate 
      For i = 1 to 3
        DirectCast(MyList, IList).Add(...)
      Next
      Return MyList
    End If
End Function

Then, I only need to know what the type of the elements of this IList is.
When the list isn’t empty, this would be simple. But in this case, as we just created the list, it IS empty.

In .Net, I can get a copy of the underlaying array of the IList (which will be an empty array), and get the type of this array:

Dim UnderlayingArrayType =  DirectCast(MyList, Dynamic).ToArray.GetType

And then I can create a new array with 1 uninitialized element; the value of this element is the default value that I need:

Dim DefaultValue = DirectCast(UnderlayingArrayType.InstantiateArray(1), IList).Item(0)

So the complete code becomes:

Public Function GetIListInstance(theType as System.Type) as IList
    If theType.Name.EndsWith("[]") Then
      Return theType.InstantiateArray(3) //return an array with 3 empty elements
    Else
      //not an array,  code for .Net: Activator.CreateInstance
      Dim MyList = TheType.Instantiate 
      //get the type of the underlaying array
      Dim UnderlayingArrayType =  DirectCast(MyList, Dynamic).ToArray.GetType
      //get a default value for this array
      Dim DefaultValue = DirectCast(UnderlayingArrayType.InstantiateArray(1), IList).Item(0)
      For i = 1 to 3
        DirectCast(MyList, IList).Add(DefaultValue)
      Next
      Return MyList
    End If
End Function

So far, so good - this works when compiled to .Net

The problem
ToArray does not exist when I compile to Island, so the code to get the default value doesn’t work here.

The question
How do I get the default value for an item of an IList when compiling for Island?

So you need something like the generic IList (which all collections implement really) to be able to get the argument type and get the sub type (ie Array of Integer already implements IList) that’s 1.

i figure you want it boxed as an Object.
For non valuetypes, it’s easy, just nul.

I don’t think we have an api for structs yet, but it’s something like:

var aType: &Type;
        var lRes := DefaultGC.New(aType.RTTI, aType.SizeOfType + aType.BoxedDataOffset);
   exit InternalCalls.Cast<Object>(lRes)

That gives “Not supported” as error in Wasm …

Doesn’t mean we can’t solve this.

I think the code should work for a List(Of something).

As List(Of Something) implements IList - bit also implements IList(Of T), it should be able to dynamically invoke the ToArray method from that interface.

Stays the problem that an Array can’t be recognized as such and even when you can, it can’t be instantiated by the InstantiateArray method when using WASM.

recognized from what? the Reflection.Type obtained from the array instance at runtime? seems if that’s a gap in Reflection, it should be possible to add support for that.

You shod just be able to call type.CreateArray(), and then create instances and shove them into each spot, no?

No, just from the system.type - no reflection used here

1 Like

@mh I think we should just log this to implement this better. Either way a nice API would help a lot here.

yeah.

Logged as bugs://E25210.

More info for what I need.

  1. When I have a System.Type, the property Name should reflect the real name.
    As an example, in WASM, the code GetType(String()).Name returns gt2_@as.
    I would have expected something like string[] (or something that has any relation to the source code).

  2. I should be able to instantiate an array from a type with the InstantiateArray method.

The above for all Island platforms.

1: Yeah that’s something we can solve in the type code itself.
2: This is trickier and needs some thinking. There are two problems:

  • Every type in Elements has it’s own vmt, type info etc; this includes arrays. What looks like an array really is RemObjects.Elements.System.Array<T>
  • Every unique generic type is also it’s own type. So there’s an ArrayInt and ArrayString and ArrayBoolean type (this is the gt2_@as, we reduce the name).
  • Every array has a set of methods
  • We can’t create functions on the the fly

The end result is that we cannot instantiate types we don’t ‘know’ about. So while you can instantiate an typeof(Array Of Integer).InstantiateArray(3), you can’t do that just from Integer.

I think I can solve 2 myself when 1 is solved …

Then I have my work cut out for me.

1 Like

bugs://E25210 was closed as fixed.

Latest IslandRTL supports this now. (Next build will also of course, but you can also grab/compile it yourself)

2 Likes

Carlo,

I debugged why the call to InstantiateArray fails.

The code of this function (github):

The call that I do is:
image

The type:

And the error that I get on this call:
image

This error would mean that the following code in the RTL (line 1296) doesn’t see that this type is an array:

So, it looks like a flag in the type isn’t set correctly when it is an array.

bugs://E25210 was reopened.

bugs://E25210 was closed as fixed.

1 Like