BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Reflection
.NET 2.0+

Late Binding with Reflection

The eighteenth part of the Reflection tutorial provides a change in direction to the previous articles, which concentrated on the extraction of information about code using reflection. This article is the first that considers late binding techniques.

Using Non-Public Constructors

If we try to use the above approach when the target class has a parameterless constructor that is not public, the activation fails with a MissingMethodException.

Assembly asm = Assembly.LoadFile(@"c:\test\MessageGenerators.dll");
Type type = asm.GetType("MessageGenerators.GoodbyeMessageGenerator");
object lateBound = Activator.CreateInstance(type);      // MissingMethodException

To use a non-public, parameterless constructor, we need to add a second, Boolean argument to the call. This parameter, when set to true, specifies that non-public constructors can be used. The code below uses the private constructor of GoodbyeMessageGenerator during activation.

Assembly asm = Assembly.LoadFile(@"c:\test\MessageGenerators.dll");
Type type = asm.GetType("MessageGenerators.GoodbyeMessageGenerator");
object lateBound = Activator.CreateInstance(type, true);
Console.WriteLine(lateBound.ToString());

/* OUTPUT

Goodbye, world!

*/

Activation with Alternative Constructors

There are many times when using the default constructor is undesirable or impossible. In these circumstances you can use another overloaded version of Activator.CreateInstance to provide the values that the preferred constructor requires. For public constructors, the overload has two parameters. The first is the type to be instantiated. The second is an object array containing the values for the constructor's parameters. These values must be of the correct types and in the right order. The array parameter is a parameter array, so you can pass the values using simple comma-separation if you prefer not to create an array beforehand.

The following code uses the public constructor of the CustomMesageGenerator class, which has a single parameter. The call to CreateInstance passes the string, "Test!", to this parameter.

Assembly asm = Assembly.LoadFile(@"c:\test\MessageGenerators.dll");
Type type = asm.GetType("MessageGenerators.CustomMessageGenerator");
object lateBound = Activator.CreateInstance(type, "Test!");
Console.WriteLine(lateBound.ToString());

/* OUTPUT

Test!

*/

Activation Using Any Public or Non-Public Constructor

The final overloaded method that we'll look at for instantiating late bound objects allows you to create objects using any constructor, be it public or private. The method receives five arguments, which are:

  • The type of object to be instantiated, provided as a System.Type object.
  • A BindingAttributes value that specifies which members may be searched when looking for a suitable constructor. We will use the NonPublic and Instance flags from the enumeration.
  • A Binder object that is used to find the constructor. We will pass null to this argument to indicate that the default binder should be used.
  • An object array containing the values to be passed to the constructor. These must be of the same types and in the same order as the desired constructor.
  • The final parameter allows you to provide a CultureInfo object that specifies the culture to be used when converting the array of arguments. We will pass null to this parameter in order to use the current culture of the target machine.

The code below instantiates a CustomMessageGenerator using the private constructor with two arguments.

Assembly asm = Assembly.LoadFile(@"c:\test\MessageGenerators.dll");
Type type = asm.GetType("MessageGenerators.CustomMessageGenerator");
object[] parameters = new object[] { "Test", "Message" };
object lateBound = Activator.CreateInstance(
    type, BindingFlags.NonPublic | BindingFlags.Instance, null, parameters, null);
Console.WriteLine(lateBound.ToString());

/* OUTPUT

Test Message

*/
19 July 2012