My hardware : MacbookPro 2023, M2, 16GB, MacOS Sonoma 14.0 running Xojo 2023 Release 3.1
Try stepping through the following loop and you will see that each step takes twice longer than the previous.
For Each p As Introspection.PropertyInfo In properties
// Any code
Next
Adding the following code in the loop, will crash Xojo randomly.
var d as new dictionary
For Each p As Introspection.PropertyInfo In properties
d.Value(p.name) = p.Value(info)
Next
Share a complete sample so we can see exactly what you see instead of:
1 Like
- The code below will run, it crashes if you try to obtain the value for propertyTypes String/Text.
- Stepping through the loop with my hardware configuration gets longer with every step
- Viewing the values and variables at runtime is a bit off as well, note that I declare the dictionary dItem within the For loop. If it is declared outside the loop, it works but the way the values of the dictionary are shown in Xojo changes.
- dItems declared INSIDE the For loop : Changes to the contents of the dictionary is correctly reflected in debug view, with the dItem selected and it’s content in view.
- ditems declared OUTSIDE the For loop, even when using “ditems = new dictionary” inside the For loop, Xojo will not remove the previous content of the dictionary from the debug view when dItem is selected and it’s content in view. You must go back, click on the dictionary item again to view it’s content, and only then it’s shown as correctly being empty (immediately after ditems = new dictionary).
Abnormal behaviour.
Public Function GetProperties(info As Introspection.TypeInfo) As Dictionary()
// Return a dictionary array, with all properties, type and values of a given class (info)
// Get property info
Var properties() As Introspection.PropertyInfo
properties = info.GetProperties
// Create a dictionary to hold our collected info
var d() as dictionary
For Each p As Introspection.PropertyInfo In properties
// Obtain the type info prior to getting property info, otherwise a crash might occur
var pType as Introspection.TypeInfo
ptype = p.PropertyType
if pType.IsValueType = true then
// Create a key with the property's name and assign it's value
var dItem as new Dictionary
dItem.Value("name") = p.Name
dItem.Value("isshared") = p.IsShared
dItem.Value("isprotected") = p.IsProtected
dItem.Value("iscomputed") = p.IsComputed
dItem.Value("ispublic") = p.IsPublic
dItem.value("isprimitive") = pType.IsPrimitive
dItem.Value("isenum") = pType.IsEnum
dItem.Value("variabletype") = ptype.FullName
// Get the value of the property (will crash on string / text types)
if ptype.FullName <> "string" and pType.FullName <> "Text" then
dItem.Value("value") = p.Value(info)
// Set an empty string / text value in those cases
else
dItem.Value("value") = ""
end if
// Add the property's info to our dictionary array
d.Add(dItem)
end if
Next
// Return the properties and values as as dictionary
return d
End Function
There’s a bug in your logic at this line (can have more):
dItem.Value("value") = p.Value(info)
It raises a Xojo assertion
OS: Windows 11
Location: ObjectGlue.h(209)
Condition: RuntimeObjectIsa(obj, mClassPtr)
Message: Xojo.Introspection.ClassInfo
I guess you don’t intend to use that object as a key there
1 Like
Thank you sir! Much appreciated.
1 Like
The PropertyInfo iterator doesn’t always return a dictionary. I suggest:
- Wrap the entire block in a Try statement (to avoid an uncaught exception crash).
- Check the type before assigning it.
For example:
Var tmpStr As String
For Each p As Introspection.PropertyInfo In properties
Var tmpVar As Variant = p.Value(sourceObject)
// Any code
If p.Name = "Dictionary" Then
var d as new dictionary
For Each p As Introspection.PropertyInfo In properties
d.Value(p.name) = p.Value(info)
Next
Else
Try
Var vTypeInt As Integer = VarType(tmpVar)
If vTypeInt > 4096 Then // It's an array
Var elemTypeInt As Integer = vTypeInt - 4096
Select Case elemTypeInt
Case 8
// It’s a string array
Case 9
// It’s an object array
End Select
Else
// Attempt to assign to a string variable … ? … you decide
// tmpStr = tmpVar.StringValue
End If
Catch e As TypeMismatchException
' Do nothing
End Try
End If
Catch ex As RuntimeException
// Handle exception, or ignore it … up to you
End Try
Please note that I did not test the code above as it is only intended to give you ideas as to a solution. Hope that helps.
He’s not expecting it to return a dictionary - he’s instantiating an array of dictionaries and returning them.
As Rick pointed out, the problem was that the OP used the wrong variable in p.Value().
1 Like