.Net Runtime Library for Delphi
Close
Dynamically Loading and Using Types

Use Type.InvokeMember to invoke a member of a type. The CreateInstance methods of various classes or Interfaces, such as TClrActivator class or _Activator Interface and TClrAssembly class or _Assembly Interface, are specialized forms of InvokeMember that create new instances of the specified type. The Binder class is used for overload resolution and argument coercion in these methods.

The following example shows the three possible combinations of argument coercion (type conversion) and member selection. In Case 1, no argument coercion or member selection is needed. In Case 2, only member selection is needed. In Case 3, only argument coercion is needed.

public class CustomBinderDriver
{
    public static void Main()
    {
        Type t = typeof(CustomBinderDriver);
        CustomBinder binder = new CustomBinder();
        BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Instance |
            BindingFlags.Public | BindingFlags.Static;
        object[] args;

        // Case 1. Neither argument coercion nor member selection is needed.
        args = new object[] {};
        t.InvokeMember("PrintBob", flags, binder, null, args);

        // Case 2. Only member selection is needed.
        args = new object[] {42};
        t.InvokeMember("PrintValue", flags, binder, null, args);

        // Case 3. Only argument coercion is needed.
        args = new object[] {"5.5"};
        t.InvokeMember("PrintNumber", flags, binder, null, args);
    }

    public static void PrintBob()
    {
        Console.WriteLine("PrintBob");
    }

    public static void PrintValue(long value)
    {
        Console.WriteLine("PrintValue({0})", value);
    }

    public static void PrintValue(string value)
    {
        Console.WriteLine("PrintValue\"{0}\")", value);
    }

    public static void PrintNumber(double value)
    {
        Console.WriteLine("PrintNumber ({0})", value);
    }
}

Overload resolution is needed when more than one member with the same name is available. The Binder.BindToMethod and Binder.BindToField methods are used to resolve binding to a single member. Binder.BindToMethod also provides property resolution through the get and set property accessors.

BindToMethod returns the MethodBase to invoke, or a null reference (Nothing in Visual Basic) if no such invocation is possible. The MethodBase return value need not be one of those contained in the match parameter, although that is the usual case.

When ByRef arguments are present, the caller might want to get them back. Therefore, Binder allows a client to map the array of arguments back to its original form if BindToMethod has manipulated the argument array. In order to do this, the caller must be guaranteed that the order of the arguments is unchanged. When arguments are passed by name, Binder reorders the argument array, and that is what the caller sees. For more information, see Binder.ReorderArgumentArray.

The set of available members are those members defined in the type or any base type. If BindingFlags.NonPublic is specified, members of any accessibility will be returned in the set. If BindingFlags.NonPublic is not specified, the binder must enforce accessibility rules. When specifying the Public or NonPublic binding flag, you must also specify the Instance or Static binding flag, or no members will be returned.

If there is only one member of the given name, no callback is necessary, and binding is done on that method. Case 1 of the code example illustrates this point: Only one PrintBob method is available, and therefore no callback is needed.

If there is more than one member in the available set, all these methods are passed to BindToMethod, which selects the appropriate method and returns it. In Case 2 of the code example, there are two methods named PrintValue. The appropriate method is selected by the call to BindToMethod.

ChangeType performs argument coercion (type conversion), which converts the actual arguments to the type of the formal arguments of the selected method. ChangeType is called for every argument even if the types match exactly.

In Case 3 of the code example, an actual argument of type String with a value of "5.5" is passed to a method with a formal argument of type Double. For the invocation to succeed, the string value "5.5" must be converted to a double value. ChangeType performs this conversion.

ChangeType performs only lossless or widening coercions, as shown in the following table.

Source type

Target type

Any type

Its base type

Any type

Interface it implements

Char

UInt16, UInt32, Int32, UInt64, Int64, Single, Double

Byte

Char, UInt16, Int16, UInt32, Int32, UInt64, Int64, Single, Double

SByte

Int16, Int32, Int64, Single, Double

UInt16

UInt32, Int32, UInt64, Int64, Single, Double

Int16

Int32, Int64, Single, Double

UInt32

UInt64, Int64, Single, Double

Int32

Int64, Single, Double

UInt64

Single, Double

Int64

Single, Double

Single

Double

Nonreference type

Reference type

The Type class has Get methods that use parameters of type Binder to resolve references to a particular member. Type.GetConstructor, Type.GetMethod, and Type.GetProperty search for a particular member of the current type by providing signature information for that member. Binder.SelectMethod and Binder.SelectProperty are called back on to select the given signature information of the appropriate methods.