Carl Camera

C# Reflection Part 7

Dealing with Remote Objects

In this final installment of C# Reflection, I provide my solutions to a couple problems I encountered after successfully retrieving the remote object I wanted.

In the first six installments, the object returned was always an intrinsic type such as string. The Invoke method always returns an object of type object and I've always shown simple casting as the final step.

string strCustName = (string) miCusNm.Invoke(oClsX,arrParms);

Remote Object

Now suppose we want to retrieve a customer name and the method returns a Cstmr object instead of a string. That is, we get a remote object back and need to grab its name property. That's a bit harder. We can combine techniques from the previous lessons to cast the object to what we need.

First we use one of the methods to get an object from the Invoke method. This is review so I'll use the simplest method from part 2. We'll change the example such that the GetNewestCustomerName method returns a Cstmr object (whose class is defined in the same DLL) rather than a string.

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]);
object oCust = miGncn.Invoke(oClsX,null);

We cannot cast it yet but we can hold it as an object for the moment. Now we'll create a System.Type object that defines the Cstmr class.

Type typCust = assem.GetType("Fully.Qual.Cstmr",true);

We already retreived the assembly object and created one System.Type object from it. We can reuse it to create another System.Type object of type Cstmr. Once that is accomplished, we then can cast the object that came back from the Invoke method to a type that we just retrieved.

object oMyCust = Activator.CreateInstance(typCust);

How is object oMyCust any different from the one that came back from the Invoke method -- oCust? They're both objects right? Not quite. oMyCust is now technically a Cstmr object and all the properties of a Cstmr object are available to us now. A simple assignment statement populates the Cstmr object with the contents returned from the refection call.

oMyCust = oCust;

After that, it's just a matter of retrieving the string property from the object.

System.Reflection.PropertyInfo p_i;
p_i = typCust.GetProperty("CustomerName");
string strCustName = (string) p_i.GetValue(oMyCust,null)

Object Arrays

And our final example is how to handle an array of foreign objects returned from a reflection call. My solution is to iterate through the object array and cast the objects in the array one at a time.

The Snippet

// create an oClsx object
Assembly assem = Assembly.LoadFrom(@"c:\path\to\file.dll");
Type typClsX = assem.GetType("Fully.Qual.ClsX",true);
object oClsX = Activator.CreateInstance(typClsX);

// retrieve the array of Cstmr objects
MethodInfo miGncn = typClsX.GetMethod("GetNewestCustomerName",new System.Type[0]);
object[] oCusts = (object[]) miGncn.Invoke(oClsX,null);

// create a Cstmr Type object and a Cstmr object
Type typCust = assem.GetType("Fully.Qual.Cstmr",true);
object oOneCust = Activator.CreateInstance(typCust);

// create a PropertyInfo object of type CustomerName
System.Reflection.PropertyInfo pi;
string strName = typCust.GetProperty(oOneCust,null);

// array to hold customer names
ArrayList alCustNames = new ArrayList();

// iterate through the returned object array casting each 
// member one at a time and grabbing its customer name 
for (int i = 0; i < oCusts.length; i++ )
   oOneCust = oCusts[i];
   string strCstName = (string) pi.GetProperty(oOneCust,null);


With the basics of C# Reflection behind us, this final article covered dealing with remote objects returned from reflection calls. We learned how to cast returned objects to remote types, as well as handling an array of remote objects.