Dynamically Loading and Using Types

Microsoft Silverlight will reach end of support after October 2021. Learn more.

Some language compilers, such as Visual Basic, enable implicit late binding. Languages that do not have syntax for implicit late binding can use reflection to bind to arbitrary members of arbitrary types at run time and invoke them. In Silverlight, reflection allows late-bound invocation only if a member's access modifiers allow it.

The following example shows how the Visual Basic compiler uses reflection implicitly to call a method on an object whose type is not known at compile time, and the reflection code that does the same thing in C#. In both cases, an exception is thrown if the PrintHello method does not exist on the object that is passed to the method.

Sub M(ByVal obj As Object)
    obj.PrintHello("Visual Basic Late Bound")
End Sub

void M(object obj)
{
    Type t = obj.GetType();
    t.InvokeMember("PrintHello",
                   BindingFlags.Public | BindingFlags.NonPublic |
                       BindingFlags.Static | BindingFlags.Instance,
                   Type.DefaultBinder, 
                   obj, 
                   new object[] { "Reflection Late Bound" });
}

Use the Activator.CreateInstance method to create objects of arbitrary type at run time. In Silverlight, you must have a Type object, and both the type and its constructor must have the appropriate accessibility level. If you supply arguments for the constructor, the default binder determines the constructor that best matches the argument types.

You can use the Load method to load an assembly at run time, list its types, and then create instances and invoke their members.

There are two ways to invoke a member of a type. You can use the Type.InvokeMember method, or you can get a reflection object that represents the member and call its Invoke method. For example, use the Type.GetMethod method to get a MethodInfo object, and then call the MethodBase.Invoke method (MethodBase is the base class of MethodInfo).

Reflection uses the Binder class for overload resolution and argument coercion. Reflection provides a default binder in the static (Shared in Visual Basic) Type.DefaultBinder property. You can also derive your own binder from the Binder class. See the code example that is provided for the Binder class.

The default binder performs only widening coercions. These are also referred to as lossless coercions, because coercing data to a wider format, for example, from Int32 to Int64 or to Double, does not lose any information. Examples of widening coercions are 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

Object