Menu
Carl Camera

C# Reflection Part 2

The first example with be the simplest and most straightforward. We'll invoke a method that takes no parameters and returns a string. What is as simple as string s = obj.Method(); takes quite a few extra steps when using reflection.

  1. Load an assembly from a known Data Link Libarary (DLL) in a known location
  2. Create a System.Type object of the class of the object you want to instantiate
  3. Create an instance of the class object
  4. Create a System.Reflection.MethodInfo object that represents the method we will invoke
  5. Invoke the method within the object we created
  6. Cast the generic object returned to its proper type

Okay, there was a lot of jargon in there and I assure you I'll try to explain each step in a straightforward manner. I've tried to use correct terms in all cases above because these are standard object-oriented terms that all software developers should be familiar with. Used correctly and consistently, they will aid communication rather than hinder it.

If you're not familiar with these terms, stay with me -- perhaps they'll become clearer as we walk through this process.

Load the Assembly

System.Reflection.Assembly assem = 
System.Reflection.Assembly.LoadFrom(@"c:\path\to\file.dll");

First, we need to find and load the DLL that has the great functionality we're going to invoke. I would wrap this in a try/catch block and provide error processing when the DLL isn't where we expect it.

Create a System.Type object

We're used to creating C# objects this way:

System.Text.StringBuilder sb = new System.Text.StringBuilder();

In this example, sb is the object instantiation of typeStringBuilder. In other words, sb is a StringBuilderobject; an instantiation of classStringBuilder. These phrases tell us that somewhere there is something called a StringBuilderclass, and the code above created an object of that type.

The object that we will create through reflection also has a class type, ClsX. The compiler is able to recognize many types of objects such as System.Text.StringBuilder but is clueless about the class of object we want. We will need to create a Type object to represent that class type.

System.Type typClsX = assem.GetType("Fully.Qual.ClsX",true);

Where did that "Fully.Qual" thing come from? That is called a namespace. The C# code that created the target DLL probably resembled this:

namespace Fully.Qual
{
   public class ClsX {

   //properties and methods for ClsX

   }
}

Always wondered what the deal was with those namespaces, huh? Here's one place we use them.

We want to be sure that we are targeting the "right" ClsX and not some other ClsX in some other namespace, so we need to specify the fully qualified namespace for the ClsX we are targeting. C# is picky that way.

The second parameter in the GetType method, specified as true indicates that you want to throw an error if there is a problem loading the DLL.

Now that we have an object representing the type of object being targeted, we can now actually create one of those objects.

Instantiate a Target Object

The method we are after is not static, so we must first create an object of type ClsX, then invoke a method on the instantiated object. So far, we've loaded the assembly, and gathered information about ClsX into a System.Type object, typClsX. Now we're going to perform the equivalent of new Fully.Qual.ClsX().

object oClsX = System.Activator.CreateInstance(typClsX);

typClsX has enough information inside it to generate an object of type ClsX. System memory is allocated and the default class constructor is called to populate any internal properties.

Once an object of type clsX is created, we can call on all the public methods within that class object.

Instantiate a MethodInfo Object

To call a method in a class object, we'll need to locate it specifically. Didn't we already do that? you may be asking yourself. In a word no. We have a class object ClsX and it may have several public methods within it. Some may even have the same name but take different parameters.

We'll now create an object to represent that unique method we're after. We must specify the method signature: its name and parameter information.

We have no parameters to pass in this example, so we will indicate "no parameters" by supplying a zero-sized Type array to the method call.

System.Reflection.MethodInfo miGncn =
   typClsX.GetMethod("GetNewestCustomerName",new System.Type[0]);

This line of code creates a MethodInfo object miGncn that holds the information for the unique public method GetNewestCustomerName() in the ClsX object.

Invoke the Method

object oName = miGncn.Invoke(oClsX,null);

That's it, almost. The information we've been working towards is in the variable oName after this line of code is executed. The second parameter null is a placeholder for parameters (that we will use in the later articles) but our example requires no parameters, so we pass null.

Curious that we call the MethodInfo object's Invoke method and pass the actual instance object oClsX as a parameter, but that's how it's done.

Cast the object returned

The Invoke method always returns an object of type object. We just need to cast it to a string to work with it.

string strNewestCust = (string) oName;

The Code

#using System.Reflection;

Assembly assem = Assembly.LoadFrom(@"c:\path\to\file.dll");
Type typClsX = assem.GetType("Fully.Qual.ClsX",true);
object oClsX = Activator.CreateInstance(typClsX);
MethodInfo miGncn = typClsX.GetMethod("GetNewestCustomerName",new System.Type[0]);
string strNewstCust = (string) miGncn.Invoke(oClsX,null);

Summary

In this article, we covered how to bind to and invoke a method at runtime through .NET Reflection. By loading the target assembly and instantiating a runtime class object, we were able to invoke a method on that class object and cast the returned object to a string.

Comments