Скачиваний:
64
Добавлен:
15.03.2015
Размер:
4.31 Mб
Скачать

582

Extreme C#

PART IV

Reflection is the capability to inspect the metadata of a program and gather information about its types. Using reflection, it’s possible to learn about program assemblies, modules, and all types of internal program elements.

This is particularly useful for design tools, supporting the automated building of code based on user selections derived from the metadata of the underlying types being used. Reflection also provides excellent support for late-bound frameworks where runtime determination is required for selecting required libraries or other functionality on-the-fly.

Discovering Program Information

The reflection API is based on a hierarchical model where higher-level items are composed of one or more lower-level items. Figure 28.1 shows this hierarchy. Assemblies, the basic unit of program distribution in C#, are at the top. Assemblies may be composed of one or more modules. Modules may have one or more types. Types are program elements such as classes, structs, delegates, and enums. Types may contain one or more fields, properties, methods, or events, depending on the type. It may be handy to think about this model as you progress through the sections of this chapter.

FIGURE 28.1

Assembly

Reflection API hierarchy.

1..*

Module

 

1..*

May be class,

Type

delegate,

 

enum, or struct

 

1..*

1..*

1..*

 

1..*

Event

Field

 

Property

Method

Reflection

CHAPTER 28

583

The primary purpose of reflection is to discover program information. The C# reflection API makes it possible to find out all information available about a program. The program elements to be searched include assemblies, modules, types, and type members. Listing 28.1 creates a class that will be reflected upon, and Listing 28.2 demonstrates how to obtain the various reflection objects and inspect their available information.

LISTING 28.1 Class to Reflect Upon: Reflected.cs

using System;

using System.Collections;

///<summary>

///Reflected Class

///</summary>

public class Reflected

{

public

int

MyField;

protected

ArrayList myArray;

public Reflected()

{

myArray = new ArrayList(); myArray.Add(“Some ArrayList Entry”);

}

public float MyProperty

{

get

{

return MyEvent();

}

}

public object this[int index]

{

get

{

if (index <= index)

{

return myArray[index];

}

else

{

return null;

}

}

set

{

28

EFLECTIONR

584

Extreme C#

PART IV

LISTING 28.1 continued

myArray.Add(value);

}

}

public float MyInstanceMethod()

{

Console.WriteLine(“Invoking Instance MyMethod.”);

return 0.02f;

}

public static float MyStaticMethod()

{

Console.WriteLine(“Invoking Static MyMethod.”);

return 0.02f;

}

public delegate float MyDelegate();

public event MyDelegate MyEvent

= new MyDelegate(MyStaticMethod);

public enum MyEnum { valOne, valTwo, valThree };

}

LISTING 28.2 Performing Reflection: Reflecting.cs

using System;

using System.Reflection;

///<summary>

///Performing Reflection.

///</summary>

class Reflecting

{

static void Main(string[] args)

{

Reflecting reflect = new Reflecting();

Assembly myAssembly

= Assembly.LoadFrom(“Reflecting.exe”);

reflect.GetReflectionInfo(myAssembly);

}

void GetReflectionInfo(Assembly myAssembly)

{

Type[] typeArr = myAssembly.GetTypes();

LISTING 28.2 continued

foreach (Type type in typeArr)

{

Console.WriteLine(“\nType: {0}\n”, type.FullName);

ConstructorInfo[] MyConstructors = type.GetConstructors();

foreach (ConstructorInfo constructor in MyConstructors)

{

Console.WriteLine(“\tConstructor: {0}”, constructor.ToString());

}

Console.WriteLine();

FieldInfo[] MyFields = type.GetFields(); foreach (FieldInfo field in MyFields)

{

Console.WriteLine(“\tField: {0}”, field.ToString());

}

Console.WriteLine();

MethodInfo[] MyMethods = type.GetMethods(); foreach (MethodInfo method in MyMethods)

{

Console.WriteLine(“\tMethod: {0}”, method.ToString());

}

Console.WriteLine();

PropertyInfo[] MyProperties

= type.GetProperties();

foreach (PropertyInfo property in MyProperties)

{

Console.WriteLine(“\tProperty: {0}”, property.ToString());

}

Console.WriteLine();

EventInfo[] MyEvents = type.GetEvents(); foreach (EventInfo anEvent in MyEvents)

{

Console.WriteLine(“\tEvent: {0}”, anEvent.ToString());

}

Console.WriteLine();

}

}

}

Reflection

CHAPTER 28

585

28

EFLECTIONR

586

Extreme C#

PART IV

And the output is:

Type: Reflecting

Constructor: Void .ctor()

Method: Int32 GetHashCode()

Method: Boolean Equals(System.Object)

Method: System.String ToString()

Method: System.Type GetType()

Type: Reflected

Constructor: Void .ctor()

Field: Int32 MyField

Method: Int32 GetHashCode()

Method: Boolean Equals(System.Object)

Method: System.String ToString()

Method: Single get_MyProperty()

Method: System.Object get_Item(Int32)

Method: Void set_Item(Int32, System.Object)

Method: Single MyInstanceMethod()

Method: Single MyStaticMethod()

Method: Void add_MyEvent(MyDelegate)

Method: Void remove_MyEvent(MyDelegate)

Method: System.Type GetType()

Property: Single MyProperty

Property: System.Object Item [Int32]

Event: MyDelegate MyEvent

Type: Reflected+MyDelegate

Constructor: Void .ctor(System.Object, UIntPtr)

Method: Single EndInvoke(System.IAsyncResult)

Method: System.IAsyncResult BeginInvoke(

System.AsyncCallback,

System.Object)

Method: Single Invoke()

Method: Void GetObjectData(

Reflection

CHAPTER 28

System.Runtime.Serialization.SerializationInfo,

System.Runtime.Serialization.StreamingContext)

Method: System.Object Clone()

Method: System.Delegate[] GetInvocationList()

Method: Int32 GetHashCode()

Method: Boolean Equals(System.Object)

Method: System.String ToString()

Method: System.Object DynamicInvoke(System.Object[])

Method: System.Reflection.MethodInfo get_Method()

Method: System.Object get_Target()

Method: System.Type GetType()

Property: System.Reflection.MethodInfo Method

Property: System.Object Target

Type: Reflected+MyEnum

Field: Int32 value__

Field: MyEnum valOne

Field: MyEnum valTwo

Field: MyEnum valThree

Method: System.String ToString(System.IFormatProvider)

Method: System.TypeCode GetTypeCode()

Method: System.String ToString(System.String,

System.IFormatProvider)

Method: Int32 CompareTo(System.Object)

Method: Int32 GetHashCode()

Method: Boolean Equals(System.Object)

Method: System.String ToString()

Method: System.String ToString(System.String)

Method: System.Type GetType()

The primary purpose of Listing 28.1 is to have a class available with all types of class members to reflect upon. It does nothing more than serve that purpose, and all of its program elements should be familiar by now.

Listing 28.2 is where the interesting bits are. The Main() method obtains an assembly object by calling the static LoadFrom() method of the Assembly class. The LoadFrom() method has a string parameter, specifying the name of the executable file, or assembly, to load.

Within the GetReflectionInfo() method, the Assembly object, myAssembly, invokes its GetTypes() method to obtain an array of all types available in the assembly.

587

28

EFLECTIONR