Reflection also enables executing dynamic code,
meaning that you can pick up types defined within an assembly, creating
instances and invoking types from Visual Basic code without having a
reference to that assembly. For example, imagine you want to load the
People.dll assembly and create and populate an instance of the Person class, as shown in Listing 1.
Listing 1. Creating and Running Dynamic Code
Imports System.Reflection Module DynamicCode
Sub DynCode() Dim asm = Assembly.LoadFrom("People.dll")
'Gets the type definition Dim personType = asm.GetType("People.Person")
'Gets the LastName property definition Dim lastNameProperty As PropertyInfo = personType. GetProperty("LastName") 'Gets a reference to the property setter Dim lastNamePropSet As MethodInfo = lastNameProperty. GetSetMethod
Dim firstNameProperty As PropertyInfo = personType. GetProperty("FirstName") Dim firstNamePropSet As MethodInfo = firstNameProperty. GetSetMethod
Dim ageProperty As PropertyInfo = personType.GetProperty("Age") Dim agePropSet As MethodInfo = ageProperty.GetSetMethod
'Creates an instance of the Person class Dim newPerson As Object = _ Activator.CreateInstance(personType)
'Each method is invoked upon the new type instance lastNamePropSet.Invoke(newPerson, New Object() {"Del Sole"}) firstNamePropSet.Invoke(newPerson, New Object() {"Alessandro"}) agePropSet.Invoke(newPerson, New Object() {32})
'Gets the BuildFullName method from the Person class Dim buildFullNameMethod = personType.GetMethod("BuildFullName")
'The method returns String but Invoke returns Object, so 'a conversion is required Dim result As String = CStr(buildFullNameMethod. Invoke(newPerson, Nothing))
Console.WriteLine(result) Console.ReadLine() End Sub End Module
|
When you have the type instance, you invoke the GetProperty method to get a reference of the desired property. This returns a PropertyInfo object. To set the property value, you need a reference to the setter method that is obtained via the GetSetMethod and that returns a MethodInfo object. (If you also want the ability to get a property value, you need to invoke instead GetGetMethod the same way.) When you have all properties, you need an instance of the class. This can be obtained by calling the Activator.CreateInstance method, which takes the type instance as the argument. The System.Activator
class contains members for creating code locally or retrieving code
from a remote location. Having an instance of the class is required
before you set properties, because it is against the instance that
property setters will be invoked. To actually run the property setter,
you call the MethodInfo.Invoke instance method; the first argument is the type instance, whereas the second argument is an array of items of type Object, each to be used as a property value. In our case each property in the Person class accepts just one value, so each array can store just one item. Similarly you can get reference to methods invoking GetMethod on the type instance, as it happens in Listing 1, to get a reference to the Person.BuildFullName method. When you call Invoke to run the method, you can pass Nothing as the second argument if the original method does not require parameters. The code simply produces the following result:
Del Sole Alessandro, Male of Age: 32
After seeing how you can call dynamic code provided by an existing assembly, let’s now see how to create code at runtime.
In
many cases you notice that you can also invoke members marked as
private or with limited visibility. Although this can seem exciting,
take care. If you invoke a private member but you are not completely
sure about its purpose, you expose your code to potential uncontrollable
dangers.