Sunday, March 16, 2008

Reflection in .Net




Though I receive poor response for non ASP.Net blogs that doesn't stop me blogging on .Net internals. Reflection though seems esoteric is a wonderful technology. Please refer by blog on Intermediate Language if you are not familiar with the structure of an assembly.

Reflection is used for inspecting the Type (class) , methods, properties, event, constructors, etc of a Assembly. It can also be used for generating code on fly.

In .Net an exe or dll is called as Assembly. An Assembly is a collection of IL, meta data and Resources. An Assembly in turn contains Modules and Modules contains Types.


I. Enumerating Types in .Net

In this example we are going to create a simple Object Browser like what you see in Visual Studio .Net by going to View menu and selecting Object Browser. Reflection in .Net requires the System.Reflecion namespace. Using the Load method of Assembly we are loading the mscorlib.dll into the cureent AppDomain. GetTypes method of Assembly can be used to return all the types defined in a module. The value returned by GetTypes is assigned to an array of Type and Displaying the contents in a listBox.




























using System.Reflection;

private void Form1_Load(object sender, EventArgs e)
{
Assembly loadAssembly = Assembly.Load("mscorlib.dll");
Type[] mytypes = loadAssembly.GetTypes();
foreach (Type types in mytypes)
listBox1.Items.Add(types);
}


II. Enumeration Properties, Methods and Events of a Class
Having displayed all the types in .Net let's go to the next level of displaying properties, methods and events of a type for this we can use PropertyInfo, MethodInfo and EventInfo classes respectively.
I am placing a TreeView and adds three root nodes viz. Methods, Propeties and Events.


Movie


using System.Reflection;

private void Form1_Load(object sender, EventArgs e) {
Type t = typeof(System.Windows.Forms.Form);

MethodInfo[] methods = t.GetMethods();
foreach (MethodInfo nextMethod in methods) {
treeView1.Nodes[0].Nodes.Add(nextMethod.ToString());
}

PropertyInfo[] properties = t.GetProperties();
foreach (PropertyInfo nextProperty in properties)
{
treeView1.Nodes[1].Nodes.Add(nextProperty.ToString());
}

EventInfo[] events = t.GetEvents();
foreach (EventInfo nextEvent in events)
{
treeView1.Nodes[2].Nodes.Add(nextEvent.ToString());
}
}


III. Inspecting AssemblyInfo Attributes


The AssemblyInfo class contains additional information about an Assembly like Assembly Description, Copyright Information, Culture, etc. You can view the AssemblyInfo file by going Solution Explorer and selecting Show All Files icon and navigating to Properties node.
Here is an extract of the contents of AssemblyInfo.

AssemblyInfo.cs

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;


[assembly: AssemblyTitle("Shalvin's Assembly Inspector")]
[assembly: AssemblyDescription("Shalvin")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Shalvin Consulting")]
[assembly: AssemblyProduct("WindowsApplication1")]
[assembly: AssemblyCopyright("Copyright © shalvin@gmail.com")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]


[assembly: ComVisible(false)]


[assembly: Guid("afa9b674-416d-4e04-bf6a-805a99e98fe5")]


Here is the code to extract the Assembly Description.

using System.Reflection;
private void Form1_Load(object sender, EventArgs e)
{
Assembly a = Assembly.GetExecutingAssembly();
Type attrType = typeof(AssemblyDescriptionAttribute);
object[] attrs = a.GetCustomAttributes(attrType, false);
if (attrs.Length > 0)
{
AssemblyDescriptionAttribute desc = (AssemblyDescriptionAttribute)attrs[0];
listBox1.Items.Add(desc.Description);
}
Type attrComp = typeof(AssemblyCompanyAttribute);
object[] atCo = a.GetCustomAttributes(attrComp, false);
if (atCo.Length > 0)
{
AssemblyCompanyAttribute aca = (AssemblyCompanyAttribute)atCo[0];
listBox1.Items.Add(aca.Company);
}
}
Object Browser in C#











using System.Reflection;

List<Type> lsTypes = new List<Type>();
private void Form1_Load(object sender, EventArgs e)
{
Assembly LoadAssembly = Assembly.Load("mscorlib.dll");
Type[] mytypes = LoadAssembly.GetTypes();
int i = 0;
foreach (Type types in mytypes)
{

treeView1.Nodes.Add(types.ToString());
MethodInfo[] mi = types.GetMethods();
treeView1.Nodes[i].Nodes.Add("Method");
foreach (MethodInfo m in mi)
{
treeView1.Nodes[i].Nodes[0].Nodes.Add(m.ToString());
}
PropertyInfo [] pi = types.GetProperties();
treeView1.Nodes[i].Nodes.Add("Properties");
foreach (PropertyInfo p in pi)
{
treeView1.Nodes[i].Nodes[1].Nodes.Add(p.ToString());
}

EventInfo[] ei = types.GetEvents();
treeView1.Nodes[i].Nodes.Add("Events");
foreach (EventInfo e1 in ei)
{
treeView1.Nodes[i].Nodes[2].Nodes.Add(e1.ToString());
}
i++;
}



1 comment: