Thursday, February 10, 2011

Reflection

The ability to discover the methods and fields in a class as well as invoke methods in a class at runtime, typically called reflection, is a feature of both Java and C#. The primary difference between reflection in Java versus reflection in C# is that reflection in C# is done at the assembly level while reflection in Java is done at the class level. Since assemblies are typically stored in DLLs, one needs the DLL containing the targeted class to be available in C# while in Java one needs to be able to load the class file for the targeted class. The examples below which enumerate the methods in a specified class should show the difference between reflection in C# and Java.
C# Code

using System;
using System.Xml;
using System.Reflection;
using System.IO;

class ReflectionSample {


public static void Main( string[] args){


Assembly assembly=null;
Type type=null;
XmlDocument doc=null;

try{
// Load the requested assembly and get the requested type
assembly = Assembly.LoadFrom("C:\\WINNT\\Microsoft.NET\\Framework\\v1.0.2914\\System.XML.dll");
type = assembly.GetType("System.Xml.XmlDocument", true);

//Unfortunately one cannot dynamically instantiate types via the Type object in C#.
doc = Activator.CreateInstance("System.Xml","System.Xml.XmlDocument").Unwrap() as XmlDocument;

if(doc != null)
Console.WriteLine(doc.GetType() + " was created at runtime");
else
Console.WriteLine("Could not dynamically create object at runtime");

}catch(FileNotFoundException){
Console.WriteLine("Could not load Assembly: system.xml.dll");
return;
}catch(TypeLoadException){
Console.WriteLine("Could not load Type: System.Xml.XmlDocument from assembly: system.xml.dll");

return;
}catch(MissingMethodException){
Console.WriteLine("Cannot find default constructor of " + type);
}catch(MemberAccessException){
Console.WriteLine("Could not create new XmlDocument instance");
}

// Get the methods from the type
MethodInfo[] methods = type.GetMethods();

//print the method signatures and parameters
for(int i=0; i < methods.Length; i++){

Console.WriteLine ("{0}", methods[i]);

ParameterInfo[] parameters = methods[i].GetParameters();

for(int j=0; j < parameters.Length; j++){
Console.WriteLine (" Parameter: {0} {1}", parameters[j].ParameterType, parameters[j].Name);
}

}//for (int i...)

}

}
Java Code

import java.lang.reflect.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;

class ReflectionTest {

public static void main(String[] args) {

Class c=null;
Document d;

try{

c = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().getClass();
d = (Document) c.newInstance();

System.out.println(d + " was created at runtime from its Class object");

}catch(ParserConfigurationException pce){
System.out.println("No document builder exists that can satisfy the requested configuration");
}catch(InstantiationException ie){
System.out.println("Could not create new Document instance");
}catch(IllegalAccessException iae){
System.out.println("Cannot access default constructor of " + c);
}

// Get the methods from the class
Method[] methods = c.getMethods();

//print the method signatures and parameters
for (int i = 0; i < methods.length; i++) {

System.out.println( methods[i]);

Class[] parameters = methods[i].getParameterTypes();

for (int j = 0; j < parameters.length; j++) {
System.out.println("Parameters: " + parameters[j].getName());
}

}
}
}
One might notice from the above code samples that there is slightly more granularity in the C# Reflection API than the Java Reflection API as can be seen by the fact that C# has a ParameterInfo class which contains metadata about the parameters of a Method while Java uses Class objects for that which lose some information such as the name of the parameter.
Sometimes there is a need to obtain the metadata of a specific class encapsulated as an object. This object is the java.lang.Class object in Java and the System.Type object in C#. To retrieve this metadata class from an instance of the target class, the getClass() method is used in Java while the GetType() method is used in C#. If the name of the class is known at compile time then one can avoid creating an instance of the class just to obtain the metadata class by doing the following
C# Code

Type t = typeof(ArrayList);

Java Code

Class c = java.util.Arraylist.class; /* Must append ".class" to fullname of class */

No comments:

Post a Comment