Reflection is what allows code to interrogate type information and metadata at runtime. One core fact allows this to happen: In the .NET Framework, data types are objects. This means that every data typewhether it is a class you wrote or a part of the base class libraryhas methods you can invoke and properties you can examine. This allows you to do things like obtain the list of methods exposed by a class, or determine the data type of a property, or even iterate through the list of parameters to a given method. You can even do things like obtain references to resources embedded with an assembly, though assemblies will be covered in Chapter 12.
In unmanaged languages, such as unmanaged C++, memory is just a collection of bytes. If you declare an array that will consume 32 bytes of memory, C++ has absolutely no idea what is contained in that 32 bytes. In contrast, the Common Language Runtime (CLR) knows exactly what is contained in every piece of memory consumed. Not only does it know where the data starts and stops, but it knows what kind of data it is. Without having access to the source code, you can use reflection to find out the data type of something in memory, and then use additional reflection tools to interrogate that type to find out its parent classes, the interfaces it implements, the methods it exposes, the properties it contains, and even the events it hosts.
A great deal of work with reflection begins by getting a reference to the data type of a particular variable in memory. This is done by calling the GetType() method on an object. This returns an object of type System.Type. As mentioned earlier, all data types within the .NET Framework are objects. Table 11.1 lists some of the most commonly used methods and properties of the Type class, the core of the Reflection functionality in the .NET Framework.
Using this table of properties and methods, you can now start to work with specific aspects of reflection, as discussed throughout the remainder of this chapter.