Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Daniel Solis - Illustrated C# 2010 - 2010.pdf
Скачиваний:
16
Добавлен:
11.06.2015
Размер:
11.23 Mб
Скачать

C H A P T E R 24

Reflection and Attributes

Metadata and Reflection

The Type Class

Getting a Type Object

What Is an Attribute?

Applying an Attribute

Predefined, Reserved Attributes

More About Applying Attributes

Custom Attributes

Accessing an Attribute

639

CHAPTER 24 REFLECTION AND ATTRIBUTES

Metadata and Reflection

Most programs are written to work on data. They read, write, manipulate, and display data. (Graphics are a form of data.) The types that you as the programmer create and use are designed for these purposes, and it is you, at design time, who must understand the characteristics of the types you use.

For some types of programs, however, the data they manipulate is not numbers, text, or graphics but information about programs and program types.

Data about programs and their types is called metadata and is stored in the programs’ assemblies.

A program can look at the metadata of other assemblies or of itself, while it’s running. When a running program looks at its own metadata, or that of other programs, it’s called reflection.

An object browser is an example of a program that displays metadata. It can read assemblies and display the types they contain, along with all the characteristics and members.

This chapter will look at how your programs can reflect on data using the Type class and how you can add metadata to your types using attributes.

Note To use reflection, you must use the System.Reflection namespace.

The Type Class

Throughout this text I’ve described how to declare and use the types available in C#. These include the predefined types (int, long, string, and so on), types from the BCL (Console, IEnumerable, and so on), and user-defined types (MyClass, MyDel, and so on). Every type has its own members and characteristics.

The BCL declares an abstract class called Type, which is designed to contain the characteristics of a type. Using objects of this class allows you to get information about the types your program is using.

Since Type is an abstract class, it cannot have actual instances. Instead, at run time, the CLR creates instances of a class derived from Type (RuntimeType) that contains the type information. When you access one of these instances, the CLR returns a reference, not of the derived type but of the base class Type. For simplicity’s sake, though, throughout the rest of the chapter, I’ll call the object pointed at by the reference an object of type Type, although technically it’s an object of a derived type that is internal to the BCL.

Important things to know about Type are the following:

For every type used in a program, the CLR creates a Type object that contains the information about the type.

Every type used in a program is associated with a separate Type object.

Regardless of the number of instances of a type that are created, there is only a single Type object associated with all the instances.

640

CHAPTER 24 REFLECTION AND ATTRIBUTES

Figure 24-1 shows a running program with two MyClass objects and an OtherClass object. Notice that although there are two instances of MyClass, there is only a single Type object representing it.

Figure 24-1. The CLR instantiates objects of type Type for every type used in a program.

You can get almost anything you need to know about a type from its Type object. Table 24-1 lists some of the more useful members of the class.

Table 24-1. Selected Members of Class System.Type

Member

Member Type

Description

 

 

 

Name

Property

Returns the name of the type.

Namespace

Property

Returns the namespace containing the type declaration.

Assembly

Property

Returns the assembly in which the type is declared. If the type is

 

 

generic, it returns the assembly in which the type is defined.

GetFields

Method

Returns a list of the type’s fields.

GetProperties

Method

Returns a list of the type’s properties.

GetMethods

Method

Returns a list of the type’s methods.

 

 

 

641

CHAPTER 24 REFLECTION AND ATTRIBUTES

Getting a Type Object

There are several ways to get a Type object. We'll look at using the GetType method and using the typeof operator.

Type object contains a method called GetType, which returns a reference to an instance’s Type object. Since every type is ultimately derived from object, you can call the GetType method on an object of any type to get its Type object, as shown here:

Type t = myInstance.GetType();

The following code shows the declarations of a base class and a class derived from it. Method Main creates an instance of each class and places the references in an array called bca for easy processing. Inside the outer foreach loop, the code gets the Type object and prints out the name of the class. It then gets the fields of the class and prints them out. Figure 24-2 illustrates the objects in memory.

using System;

 

 

using System.Reflection;

 

// Must use this namespace

class BaseClass

 

 

{ public int BaseField = 0; }

 

 

class DerivedClass : BaseClass

 

 

{ public int DerivedField = 0; }

 

 

class Program

 

 

{

 

 

static void Main( )

 

 

{

 

 

var bc = new BaseClass();

 

 

var dc = new DerivedClass();

 

 

BaseClass[] bca = new BaseClass[] { bc, dc };

 

foreach (var v in bca)

 

 

{

 

 

Type t = v.GetType();

 

// Get the type.

Console.WriteLine("Object type : {0}", t.Name);

FieldInfo[] fi = t.GetFields();

// Get the field info.

foreach (var f in fi)

 

 

Console.WriteLine("

Field : {0}", f.Name);

Console.WriteLine();

 

 

}

 

 

}

 

 

}

 

 

642

CHAPTER 24 REFLECTION AND ATTRIBUTES

This code produces the following output:

Object type : BaseClass

Field : BaseField

Object type : DerivedClass

Field : DerivedField

Field : BaseField

Figure 24-2. The base class and derived class objects along with their Type objects

643

CHAPTER 24 REFLECTION AND ATTRIBUTES

You can also use the typeof operator to get a Type object. Just supply the name of the type as the operand, and it returns a reference to the Type object, as shown here:

Type t = typeof( DerivedClass );

 

 

Operator

Type you want the Type object for

The following code shows a simple example of using the typeof operator:

using System;

 

using System.Reflection;

// Must use this namespace

namespace SimpleReflection

 

{

 

class BaseClass

 

{ public int MyFieldBase; }

 

class DerivedClass : BaseClass

 

{ public int MyFieldDerived; }

 

class Program

 

{

 

static void Main( )

 

{

 

Type tbc = typeof(DerivedClass);

// Get the type.

Console.WriteLine("Result is {0}.", tbc.Name);

Console.WriteLine("It has the following fields:"); // Use the type. FieldInfo[] fi = tbc.GetFields();

foreach (var f in fi) Console.WriteLine(" {0}", f.Name);

}

}

}

This code produces the following output:

Result is DerivedClass.

It has the following fields:

MyFieldDerived

MyFieldBase

644

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]