Programming C#: Attributes and Reflection
Pages: 1, 2, 3, 4, 5, 6, 7, 8, 9
Type Discovery
You can use reflection to explore and examine the contents of an assembly. You can find the types associated with a module; the methods, fields, properties, and events associated with a type, as well as the signatures of each of the type's methods; the interfaces supported by the type; and the type's base class.
To start, load an assembly dynamically with the Assembly.Load static method. The Assembly class encapsulates the actual assembly itself, for purposes of reflection. The signature for the Load method is:
public static Assembly.Load(AssemblyName)
For the next example, pass in the Core Library to the Load method. MsCorLib.dll has the core classes of the .NET Framework:
Assembly a = Assembly.Load("Mscorlib.dll");
Once the assembly is loaded, you can call GetTypes( ) to return an array of Type objects. The Type object is the heart of reflection. Type represents type declarations: classes, interfaces, arrays, values, and enumerations:
Type[] types = a.GetTypes( );
The assembly returns an array of types that you can display in a foreach loop, as shown in Example 18-3. Because this listing uses the Type class, you will want to add a using statement for the System.Reflection namespace.
Example 18-3: Reflecting on an assembly
namespace Programming_CSharp
{
using System;
using System.Reflection;
public class Tester
{
public static void Main( )
{
// what is in the assembly
Assembly a = Assembly.Load("Mscorlib.dll");
Type[] types = a.GetTypes( );
foreach(Type t in types)
{
Console.WriteLine("Type is {0}", t);
}
Console.WriteLine(
"{0} types found", types.Length);
}
}
}
The output from this would fill many pages. Here is a short excerpt:
Type is System.TypeCode Type is System.Security.Util.StringExpressionSet Type is System.Runtime.InteropServices.COMException Type is System.Runtime.InteropServices.SEHException Type is System.Reflection.TargetParameterCountException Type is System.Text.UTF7Encoding Type is System.Text.UTF7Encoding$Decoder Type is System.Text.UTF7Encoding$Encoder Type is System.ArgIterator Type is System.Runtime.Remoting.JITLookupTable Type is System.Runtime.Remoting.IComponentServices Type is System.Runtime.Remoting.ComponentServices 1429 types found
This example obtained an array filled with the types from the Core Library and printed them one by one. The array contained 1,429 entries on my machine.
Reflecting on a Type
You can reflect on a single type in the mscorlib assembly as well. To do so, you extract a type from the assembly with the GetType( ) method, as shown in Example 18-4.
Example 18-4: Reflecting on a type
namespace Programming_CSharp
{
using System;
using System.Reflection;
public class Tester
{
public static void Main( )
{
// examine a single object
Type theType =
Type.GetType(
"System.Reflection.Assembly");
Console.WriteLine(
"\nSingle Type is {0}\n", theType);
}
}
}
Output:
Single Type is System.Reflection.Assembly
Finding all type members
You can ask the Assembly type for all its members using the GetMembers( ) method of the Type class, which lists all the methods, properties, and fields, as shown in Example 18-5.
Example 18-5: Reflecting on the members of a type
namespace Programming_CSharp
{
using System;
using System.Reflection;
public class Tester
{
public static void Main( )
{
// examine a single object
Type theType =
Type.GetType(
"System.Reflection.Assembly");
Console.WriteLine(
"\nSingle Type is {0}\n", theType);
// get all the members
MemberInfo[] mbrInfoArray =
theType.GetMembers( );
foreach (MemberInfo mbrInfo in mbrInfoArray )
{
Console.WriteLine("{0} is a {1}",
mbrInfo, mbrInfo.MemberType);
}
}
}
}
Once again the output is quite lengthy, but within the output you see fields, methods, constructors, and properties, as shown in this excerpt:
System.String s_localFilePrefix is a Field Boolean IsDefined(System.Type) is a Method Void .ctor( ) is a Constructor System.String CodeBase is a Property System.String CopiedCodeBase is a Property
Finding type methods
You might want to focus on methods only, excluding the fields, properties, and so forth. To do so, you remove the call to GetMembers( ):
MemberInfo[] mbrInfoArray =
theType.GetMembers(BindingFlags.LookupAll);
and add a call to GetMethods( ):
mbrInfoArray = theType.GetMethods( );
The output now is nothing but the methods:
Output (excerpt):
Boolean Equals(System.Object) is a Method
System.String ToString( ) is a Method
System.String CreateQualifiedName(
System.String, System.String) is a Method
System.Reflection.MethodInfo get_EntryPoint( ) is a Method
Finding particular type members
Finally, to narrow it down even further, you can use the FindMembers method to find particular members of the type. For example, you can narrow your search to methods whose names begin with the letters Get.
To narrow the search, you use the FindMembers method, which takes four parameters: MemberTypes, BindingFlags, MemberFilter, and object.
MemberTypes- A
MemberTypesobject that indicates the type of the member to search for. These includeAll,Constructor,Custom,Event,Field,Method,Nestedtype,Property, andTypeInfo. You will also use theMemberTypes.Methodto find a method. BindingFlags- An enumeration that controls the way searches are conducted by reflection. There are a great many
BindingFlagvalues, includingIgnoreCase,Instance,Public,Static, and so forth. TheBindingFlagsdefault member indicates no binding flag, which is what you want because you do not want to restrict the binding. MemberFilter- A delegate (see Chapter 12) that is used to filter the list of members in the MemberInfo array of objects. The filter you'll use is
Type.FilterName, a field of theTypeclass used for filtering on a name. Object- A string value that will be used by the filter. In this case you'll pass in "
Get*" to match only those methods that begin with the lettersGet.
The complete listing for filtering on these methods is shown in Example 18-6.
Example 18-6: Finding particular members
namespace Programming_CSharp
{
using System;
using System.Reflection;
public class Tester
{
public static void Main( )
{
// examine a single object
Type theType = Type.GetType(
"System.Reflection.Assembly");
// just members which are methods beginning with Get
MemberInfo[] mbrInfoArray =
theType.FindMembers(MemberTypes.Method,
BindingFlags.Default,
Type.FilterName, "Get*");
foreach (MemberInfo mbrInfo in mbrInfoArray )
{
Console.WriteLine("{0} is a {1}",
mbrInfo, mbrInfo.MemberType);
}
}
}
Output (excerpt):
System.Type[] GetTypes( ) is a Method System.Type[] GetExportedTypes( ) is a Method System.Type GetType(System.String, Boolean) is a Method System.Type GetType(System.String) is a Method System.Reflection.AssemblyName GetName(Boolean) is a Method System.Reflection.AssemblyName GetName( ) is a Method Int32 GetHashCode( ) is a Method

