Issue dated - 13th January 2003

-


CURRENT ISSUE
INDIA NEWS
INDIA TRENDS
STOCK FILE
OPINION
NEWS ANALYSIS
E-BUSINESS
TECHNOLOGY
TECHSPACE
FOCUS
PRODUCTS
EVENTS
COLUMNS
TECH FORUM

THE C# COLUMN

BETWEEN THE BYTES
TECHNOLOGY
SPECIALS <NEW>
HMA BANKBIZ
EC SERVICES
ARCHIVES/SEARCH
IT APPOINTMENTS
WRITE TO US
SUBSCRIBE/RENEW
CUSTOMER SERVICE
ADVERTISE
ABOUT US

 Network Sites
  IT People
  Network Magazine
  Business Traveller
  Exp. Hotelier & Caterer
  Exp. Travel & Tourism
  Exp. Backwaters
  Exp. Pharma Pulse
  Exp. Healthcare Mgmt.
  Express Textile
 Group Sites
  ExpressIndia
  Indian Express
  Financial Express

 
Front Page > TechSpace > Story Print this Page|  Email this page

Reading metadata using reflection

The C# Column - Yashawant Kanetkar

Every managed application in .NET is deployed as an assembly and every assembly defines certain types. These types are revealed in the form of metadata. Metadata is the data written in binary form in Portable Executable (PE) file. Metadata gives a detailed description of types and external assemblies that are used by the types. For example, metadata of a class would completely define the class including its methods, parameters of methods, calling convention, class’s data members and visibility of class members. We can read this information from metadata using reflection. The .NET base class library has provided namespaces and classes for this encapsulated in System.Reflection namespace. Using reflection we can read types from assembly, create instances of types dynamically, invoke methods, etc. Before we discuss how to use reflection technology, we would see how types are arranged in metadata and what purpose metadata serves.

One of the biggest benefits of .NET is that code written for it can be used by different languages. A function defined in VC++ can be called from VB. But as both the languages use different syntax, there must be some common format to enable interoperability. This common format is metadata. Another benefit of using metadata is that it eliminates the need of specifying the import library in the linker options. This is possible because metadata is written in the same EXE or DLL file as the code itself. The information in metadata is arranged in the hierarchy shown in Diagram 1.


Diagram 1

Reflection allows us to either read data from assembly or write data to assemblies. The System.Reflection namespace contains classes to read an assembly, whereas, System.Reflection.Emit namespace contains classes to write to the assembly. In this article, we would firstly create an application that lists all the types of selected assembly. Then, on selecting a type, its members get displayed.

Create a Windows Application and design a form as shown in the following figure.

The variables and events of different controls in the form are given in the following table.

Control Variable Event
TextBox aname
Load Button load Click
Types ListBox list SelectedValueChanged
Methods and listmethods
Constructors
ListBox
Properties listprop
ListBox
Events ListBox listeve

Also add the OpenFileDialog control to the form. On clicking the ‘Load’ button the standard ‘Open’ dialog box gets displayed. If the user selects an assembly and clicks the OK button, its path gets displayed in the text box, the assembly gets loaded in memory and its types get displayed in the list box. To do this, we have added the Click event handler as shown below.

private void load_Click    ( object sender, System.EventArgs e )
{
	openFileDialog1.InitialDirectory = 
	@”C:\WINDOWS\Microsoft.NET\ Framework\v1.0.3705” ;
	openFileDialog1.Filter = “Assemblies (*.dll)|*.dll” ;
	if ( openFileDialog1.ShowDialog( ) == DialogResult.OK )
	{
		list.Items.Clear( ) ;
		aname.Text = openFileDialog1.FileName ;
		Assembly a ;
		try
		{
			a = Assembly.LoadFrom 
			(aname.Text);
			tarray = a.GetExportedTypes( ) ;
		}
		catch ( Exception ex )
		{
			MessageBox.Show ( “Error in loading assembly” ) ;
			return;
		}
		foreach ( Type type in tarray ) 
		list.Items.Add ( type.FullName ) ;
		list.SetSelected ( 0, true ) ; 
   }
}

Here, firstly we have set the default folder where all .NET framework assemblies are stored. We have also set the Filter property to ‘.dll’ so that only assemblies would be listed in the dialog. To load the selected assembly, we have read the assembly path from the text box and called the LoadFrom( ) static method of the Assembly class. This method returns a reference to the Assembly object. Using this reference, we have called the GetExportedTypes( ) method that returns an array of types available in the assembly. tarray is an array of Type objects. Add this array as a private data member. The types returned by the GetExportedTypes( ) method are added to the list box in the foreach loop using the Add( ) method.

Now let us write the code to display type members in respective list boxes, if any type is selected. The SelectedValueChanged event handler is given below.

private void selchange (object sender,System.EventArgs e)
{
		int index = list.SelectedIndex;
		Type t = tarray[index];
		listmethods.Items.Clear();
		listprop.Items.Clear();
		listeve.Items.Clear();
		ConstructorInfo [] ci = t.GetConstructors();
		foreach (ConstructorInfo c in ci)
		listmethods.Items.Add (c);
		PropertyInfo [] pi = t.GetProperties();
		foreach (PropertyInfo p in pi)
		listprop.Items.Add(p);
		EventInfo [] ei = t.GetEvents();
		foreach (EventInfo ev in ei)
		listeve.Items.Add(ev);
		MethodInfo [] mi = t.GetMethods(BindingFlags.Instance | 
BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic);
		String str = “”;
		foreach (MethodInfo m in mi)
		{
			if (t == m.DeclaringType) 
			{
				str = m.Name;
				str += “ ( “ ;
				ParameterInfo [] pif = m.GetParameters() ;
				foreach (ParameterInfo p in pif)
				{
					str += p.ParameterType;
					str += “ “;
					str += p.Name;
					str += “, “;
				}
				int c = str.LastIndexOf (‘,’);
				if (c != -1)
				str = str.Remove (c, 1);
				str += “ )”;
				listmethods.Items.Add (str);
			}
		}
}

To display members we must first obtain the item selected from the list box. We have done so by using the SelectedIndex property of the ListBox class. We have retrieved the selected type from the tarray array.

The Type class contains various methods to access members of a type. We have used the same to read constructors, methods, properties and events of the selected type. These methods return a reference to an array containing respective members. We have listed the members in the respective list boxes. To the GetMethods( ) method we have passed certain flags. These flags indicate that we intend to read the instance methods, methods that are not inherited from base type and methods that are public as well as non-public. We can mention this flag in all the other methods as well. Since method name and its parameters need to be read separately, we have used string concatenation to form a string that looks like a prototype declaration of method. Again, we have listed only those methods that directly belong to this type. We have used the DeclaringType property of the MethodInfo class.

We would now see a small example that loads a user-created assembly, obtains a class type, creates its instance and invokes a method defined in the assembly. Here is the code...

Assembly a = Assembly.LoadFrom(“c:\\mymath.dll”);
Type t = a.GetType (“mymath”);
MethodInfo m = t.GetMethod(“add”);
Object obj = Activator.CreateInstance (t);
Object[ ] arg = new Object [2];
arg[0] = 10;
arg[1] = 20;
m.Invoke(obj, arg);

mymath is the name of class written in ‘mymath.dll’. To the GetMethod( ) method we have passed the name of the method we want to invoke. Next, by calling the CreateInstance( ) method we have created an object of type stored in t and collected its reference in obj. The add( ) method takes two integers. So, we have created an array of objects arg. Lastly, we have called the add( ) method by using the Invoke( ) method. The add( ) method adds the two integers passed to it and displays the result.

Yashavant Kanetkar, one of the first Express Computer columnists, is an established software expert, speaker and author with several best-sellers to his credit, including titles like “Let Us C” and the “Fundas” series. Contact him at kanet@nagpur.dot.net.in
<Back to top>


© Copyright 2000: Indian Express Group (Mumbai, India). All rights reserved throughout the world. This entire site is compiled in
Mumbai by The Business Publications Division of the Indian Express Group of Newspapers.
Please contact our Webmaster for any queries on this site.