Module

# Introspection

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Description

Gets information about a program's structure at runtime. Classes and methods in the <span class="title-ref">Introspection</span> module have Public rather than Global scope, so references to them must include the module name.

## Methods

<div class="rst-class">

table-centered_column_4

</div>

| Name                             | Parameters                                                | Returns                                          | Shared |
|----------------------------------|-----------------------------------------------------------|--------------------------------------------------|--------|
| `GetType<introspection.gettype>` | base As `Object</api/data_types/additional_types/object>` | `TypeInfo</api/language/introspection/typeinfo>` |        |

## Method descriptions

<div id="introspection.gettype">

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

</div>

<div class="rst-class">

forsearch

</div>

Introspection.GetType

**GetType**(base As `Object</api/data_types/additional_types/object>`) As `TypeInfo</api/language/introspection/typeinfo>`

> Returns a `TypeInfo</api/language/introspection/typeinfo>` object for the passed object. Each `TypeInfo</api/language/introspection/typeinfo>` instance is unique and immutable, so two objects of the same class will always return the same `TypeInfo</api/language/introspection/typeinfo>`.
>
> The following example gets information about the class instance and displays the name of its class.
>
> ``` xojo
> Var tcp As New TCPSocket
> Var t As Introspection.TypeInfo
> t = Introspection.GetType(tcp)
>
> MessageBox("My class name is " + t.Name)
> ```
>
> <div class="note">
>
> <div class="title">
>
> Note
>
> </div>
>
> You cannot pass an array as a parameter to this function.
>
> </div>

## Notes

<span class="title-ref">Introspection</span> returns all class members even if they are only used internally by the Xojo framework. If you suspect that a particular class member may be only for use by the framework, see if it autocompletes in the Code Editor. If the class member does not autocomplete, it's not for public use.

## Sample code

The following example in the Pressed event of a `Button</api/user_interface/desktop/desktopbutton>` in a window gets information about the class instance and displays the name of its class. See the examples for the `AttributeInfo</api/language/introspection/attributeinfo>`, `ConstructorInfo</api/language/introspection/constructorinfo>`, `MemberInfo</api/language/introspection/memberinfo>`, `MethodInfo</api/language/introspection/methodinfo>`, `PropertyInfo</api/language/introspection/propertyinfo>`, `TypeInfo</api/language/introspection/typeinfo>`, and `ParameterInfo</api/language/introspection/parameterinfo>` for examples of those classes.

``` xojo
Var tcp As New TCPSocket
Var t As Introspection.TypeInfo
t = Introspection.GetType(tcp)

MessageBox("My class name is " + t.Name)
```

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

The following example shows how <span class="title-ref">Introspection</span> can massively simplify code, reduce the size of an app, and obviate the need to manually update the code when new exceptions are added to the language:

To enable error reporting one can:

- Add a window win_ReportError
- Add a module Module_ErrorHandling with function: HandleException(error As RuntimeException, source As String) As Boolean

Normally one could just read the stack trace for error reporting, however as the stack on Macs does not have the required information on where the error occurred you need to put in a bit more work to get this info.

In each method or event call the HandleException function with:

``` xojo
Exception err

If Not Module_ErrorHandling.HandleException(err, CurrentMethodName) Then ' Specifies location
  ' calls the HandleException method and passes it the error type 
  ' and the location of where the error happened
  ' if that doesn't work then 
  Raise err 
End If 
```

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Now instead of writing this code:

``` xojo
Function HandleException(error As RuntimeException, source As String) As Boolean
  Var message As String

  If error IsA FunctionNotFoundException Then
    message = "FunctionNotFoundException in " + source

  ElseIf error IsA IllegalCastException Then
    message = "IllegalCastException in " + source

  ElseIf error IsA IllegalLockingException Then
    message = "IllegalLockingException in " + source

  ElseIf error IsA InvalidParentException Then
    message = "Unhandled InvalidParentException error in " + source

  ElseIf error IsA KeyChainException Then
    message = "KeyChainException in " + source

  ElseIf error IsA KeyNotFoundException Then
    message = "KeyNotFoundException in " + source

  ElseIf error IsA NilObjectException Then
    message = "NilObjectException in " + source

  ElseIf error IsA OLEException Then
    message = "Unhandled OLEException error in " + source

  ElseIf error IsA OutOfBoundsException Then
    message = "OutOfBoundsException in " + source

  ElseIf error IsA OutOfMemoryException Then
    message = "OutOfMemoryException in " + source

  ElseIf error IsA XojoScriptAlreadyRunningException Then
    message = "Unhandled XojoScriptAlreadyRunningException error in" + source

  ElseIf error IsA XojoScriptException Then
    message = "Unhandled XojoScriptException error in " + source

  ElseIf error IsA RegExException Then
    message = "RegExException in " + source

  ElseIf error IsA RegExSearchPatternException Then
    message = "RegExSearchPatternException in " + source

  ElseIf error IsA RegistryAccessErrorException Then
    message = "RegExSearchPatternException in " + source

  ElseIf error IsA RuntimeException Then
    message = "Unhandled RuntimeException error in " + source

  ElseIf error IsA RegistryAccessErrorException Then
    message = "Unhandled RegistryAccessErrorException error in " + source

  ElseIf error IsA ServiceNotAvailableException Then
    message = "Unhandled ServiceNotAvailableException error in " + source

  ElseIf error IsA ShellNotAvailableException Then
    message = "ShellNotAvailableException in " + source

  ElseIf error IsA ShellNotRunningException Then
    message = "ShellNotRunningException in " + source

  ElseIf error IsA SpotlightException Then
    message = "ShellNotRunningException in " + source

  ElseIf error IsA StackOverflowException Then
    message = "StackOverflowException in " + source

  ElseIf error IsA ThreadAlreadyRunningException Then
    message = "ThreadAlreadyRunningException in " + source

  ElseIf error IsA TypeMismatchException Then
    message = "TypeMismatchException in " + source

  ElseIf error IsA UnsupportedFormatException Then
    message = "UnsupportedFormatException in " + source

  Else
    Return False

  End If

  Var win_ReportThisError As New win_ReportError(message)
  win_ReportThisError.Show

  Return True

Exception
  MessageBox("HandleException Error")
  Return True
End Function
```

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

You can use <span class="title-ref">Introspection</span> and write:

``` xojo
Function HandleException(error As RuntimeException, source As String) As Boolean
  ' can use Introspection instead of if…elseif statement
  Var message As String = Introspection.GetType(error).FullName + " in " + source
  Var win_ReportThisError As New win_ReportError(message)
  win_ReportThisError.Show

  Return True

Exception  

  MessageBox("HandleException Error")
  Return True
End Function
```

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

This not only reduces the code but also the app size — a simple demo app has:

- with the if…elseif statement: 15.7 MB
- comment out the two XojoScript exceptions 5.2 MB
- use the <span class="title-ref">Introspection</span> method 4.9 MB (still works with XojoScript exceptions)

Another advantage is that whenever new Exceptions are added to the Xojo language, you don't need to add them manually to the ElseIf construct but they will be automatically dealt with as well through the generic <span class="title-ref">Introspection</span> system.

Consider you have an array of objects that you like to sort:

``` xojo
Var dates() As DateTime
dates.Add(New DateTime(1980, 4, 11))
dates.Add(New DateTime(1912, 1, 30))
dates.Add(New DateTime(1955, 10, 23))
```

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

You cannot write

``` xojo
dates.Sort
```

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

because the `Arrays.Sort<arrays.sort>` method only works with simple types (Integer, String etc.).

The following method, when added to a module so that it's globally visible, can be used to accomplish this.

Write:

``` xojo
dates.SortByProperty("SQLDateTime")
```

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

By using <span class="title-ref">Introspection</span>, the method will find the "SQLDateTime" property of the Date object and then fetch its values to use with the `Arrays.SortWith<arrays.sortwith>` method.

Here is the *SortByProperty* method that you should put into a module:

``` xojo
Sub SortByProperty(Extends objs() As Object, propName As String)
  ' This is a convenience function for sorting an array of objects by one of their properties.
  ' It only works with properties of simple types such as String and Integer.
  ' Written by Sept 23, 2015 by Thomas Tempelmann. Use as you like.

  If objs.LastIndex <= 0 Then
    ' No sorting necessary
    Return
  End If

  ' Get the type (class) of one of the objects in the array
  Var obj As Object = objs(0)
  Var ti As Introspection.TypeInfo = Introspection.GetType(obj)

  ' Find the property by its name
  Var 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
    Var exc As New KeyNotFoundException
    exc.Message = "Class '" + ti.FullName + "' has no property named '" + propName + "'"
    Raise exc
  End If

  ' Fetch the values for sorting, then sort. Do this for various types
  Var typeName As String = propInfo.PropertyType.FullName
  If typeName = "String" Then
    Var sortValues() As String
    For Each obj In objs
      sortValues.Add(propInfo.Value(obj))
    Next
    sortValues.SortWith(objs)

  ElseIf typeName = "Int32" Then ' AKA Integer
    Var sortValues() As Int32
    For Each obj In objs
      sortValues.Add(propInfo.Value(obj))
    Next
    sortValues.SortWith(objs)

  Else
    ' You may have to add your own cases for other sortable types if you get here

    Var exc As New TypeMismatchException
    exc.Message = "Property of '" + ti.FullName + "' is not of a simple sortable type"
    Raise exc

  End If
End Sub
```

## Compatibility

|                       |     |
|-----------------------|-----|
| **Project Types**     | All |
| **Operating Systems** | All |

<div class="seealso">

`ConstructorInfo</api/language/introspection/constructorinfo>`, `AttributeInfo</api/language/introspection/attributeinfo>`, `MemberInfo</api/language/introspection/memberinfo>`, `MethodInfo</api/language/introspection/methodinfo>`, `ParameterInfo</api/language/introspection/parameterinfo>`, `PropertyInfo</api/language/introspection/propertyinfo>`, `TypeInfo</api/language/introspection/typeinfo>` classes; `GetTypeInfo</api/language/introspection/gettypeinfo>` function, `ObjectIterator</api/language/introspection/objectiterator>`.

</div>
