I recently wanted to sort an array of a custom class by one of its properties.
So I came up with a function that uses Introspection for this, so that it can be used for any array and any simple property without extra work, like this:
[code] dim dates() as Date
dates.Append new Date (1980, 4, 1)
dates.Append new Date (1912, 1, 30)
dates.Append new Date (1955, 10, 23)
dates.SortByProperty “SQLDateTime”[/code]
I’ve added the function as an example to the offocial Xojo docs, here: http://documentation.xojo.com/index.php/Introspection#Examples
Inspired by Thomas’ SortByProperty method, I adapted it to find an instance of a class in an array by one of its properties. I now use this instead of writing a Find method for each array of different classes.
Function FindByProperty(extends objs() as Object, propName as String, targetValue as Variant) As Integer
// This is a convenience function for finding an element in an array of objects by name.
// It only works with properties of simple types such as String and Integer.
// Adapted by Tim Brunson on 2016-8-19 from the FindByProperty method written by Sept 23, 2015 by Thomas Tempelmann. Use as you like.
// Returns the index of the (first) matching element, and -1 if none is found.
dim i as Integer
if objs.Ubound < 0 then
return -1
end if
// Get the type (class) of one of the objects in the array
dim obj as Object = objs(0)
dim ti as Introspection.TypeInfo = Introspection.GetType(obj)
// Find the property by its name
dim propInfo as Introspection.PropertyInfo
for each pi as Introspection.PropertyInfo in ti.GetProperties()
if pi.Name = propName then
propInfo = pi
exit
end if
next
if propInfo = nil then
// Unknown property
dim exc as new KeyNotFoundException
exc.Message = "Class '" + ti.FullName + "' has no property named '" + propName + "'"
raise exc
end if
select case targetValue.Type
case Variant.TypeString
for i = 0 to objs.Ubound
if targetValue.StringValue = propInfo.Value(objs(i)) then Return i
next
Return -1
case Variant.TypeInteger
for i = 0 to objs.Ubound
if targetValue.IntegerValue = propInfo.Value(objs(i)) then Return i
next
Return -1
case else
// You may have to add your own cases for other searchable types if you get here
dim exc as new TypeMismatchException
exc.Message = "Property of '" + ti.FullName + "' is not of a simple searchable type"
raise exc
end select
End Function
Thanks for the code Tim. Just so you know there’s a couple unhandled edge cases.
dim obj as Object = objs(0)
objs(0) may be nil
Also the array may be used polymorphicly so the type of the first non-nil element doesn’t include all the properties of subsequent element types. This is less of a concern as all non-nil elements will at least have all properties of the arrays type. What I mean is, if you know the array contains subclass types you can’t search for those subclass properties. Hmm, I guess that’d be a dumb thing to do anyways