Working with ReflectionThis next section provides an overview of reflection and how it works. In addition, this section provides examples of using reflection to query information at runtime. Introduction to ReflectionAs mentioned in this chapter's introduction, reflection is a technology that allows managed code to inspect various aspects of the code and metadata at runtime. This allows managed code to do simple things such as obtaining a list of the properties belonging to an object instance, or even more complex things such as querying custom attributes or obtaining an image from a resource embedded within an assembly. How Reflection WorksOne of the main keys to making reflection work is understanding that data types are objects. Understanding this point is crucial to understanding reflection. Managed code can obtain an object instance that is a System.Type. Because you can treat a data type as an object, you can execute methods and query properties of that data type. Methods on the System.Type class enable you to query the list of members belonging to that type or a list of attributes, methods, and so on. One of the main differences between a managed environment and an unmanaged environment is that the .NET managed environment not only manages the in-memory instances, but the Common Language Runtime actually knows the data type information about each instance it is managing. With a traditional, unmanaged language, data is stored in memory. If your code creates an array of 16-bit integers that is two elements long, there could be a sequential set of four bytes that represents that array. With this unmanaged language, there is no real information about what kind of data is represented by that array; the only information about the code is contained in the code itself. With a managed environment, like the .NET Framework, not only would the array data be stored, but the data type of the array would also be stored. For example, when you create an instance of a class Porsche, the Common Language Runtime is managing that class. At runtime, without having access to the source code that generated that class, managed code can inspect Porsche and determine that it inherits from SportsCar, which in turn inherits from Car. If the only information maintained in the Porsche class is a simple integer, then, in an unmanaged environment, a Porsche that inherited from SportsCar that inherited from Car would look identical to an integer representing a simple loop counter. By maintaining reflection information at runtime, managed code becomes extremely powerful and has several advantages over its unmanaged counterparts. Discovering Type Information at RuntimeYou probably do some things in your code quite often without realizing that you are using reflection or capabilities provided by reflection. Take a look at the following code snippet
This code performs some action if the variable theCar is of the type Porsche. The is keyword not only checks the instantiation type, but also checks the types of all inherited ancestors. The typeof operator is another keyword that you might have used in reflection and not known that you were doing so. When applied to an object instance, typeof returns the System.Type corresponding to that object, as shown in the following code line: System.Type carType = typeof(myPorsche); As you can see, the typeof operator returns an instance of the System.Type class. After you have obtained an instance of the System.Type class using any of several different methods, you can accomplish quite a few things. Table 11.1 lists some of the more commonly used methods and properties of the System.Type class. Read the code in Listing 11.1 and the explanation that follows. Listing 11.1 provides a sample of using reflection to obtain information about a class at runtime. Listing 11.1. Reflection Exampleusing System; namespace ReflectionSample { public class Car This sample starts by creating a hierarchy of classes The first thing the example does with Reflection is to list all the different methods The second piece of code Finally, code that many programmers find the most interesting Porsche -> SportsCar -> Car -> Object This output further reinforces the notion that all classes in the .NET Framework inherit from System.Object. ![]() |