Reflection Technology
Reflection (reflection) is. net, which can be obtained at runtime through radiation. net, including methods, attributes, events, and constructor. You can also obtain the name, qualifier, and parameters of each member. With reflection, you can be familiar with every type. If you obtain information about the constructor, you can directly create an object, even if the object type is unknown during compilation.
1... Net executable ApplicationProgramStructure
ProgramCodeAfter compilation, we first need to understand the structure of the executable application.
The application structure can be divided into application domain-assembly-module-type-member layers, and the common language runtime loader manages the application domain, such management includes loading each assembly to the corresponding application domain and controlling the memory layout of the type hierarchy of each set.
The Assembly contains modules, while the module contains types and types, and reflection provides encapsulated assembly, module, and type objects. We can use reflection to dynamically create instances of the type, bind the type to an existing object or obtain the type from the existing object, and then call the method of the type or access its fields and attributes. Reflection is usually used for the following purposes.
(1) Use Assembly to define and load the Assembly, load the module in the assembly list, and locate the type in this Assembly and create instances of this type.
(2) Use the module to understand the Assembly containing the module and the classes in the module, and obtain all global methods or other specific non-Global methods defined on the module.
(3) Use constructorinfo to understand the name, parameters, access modifiers (such as pulic or private) and implementation details (such as abstract or virtual) of the constructorinfo. Use the getconstructors or getconstructor method of type to call a specific constructor.
(4) use methodinfo to understand the method name, return type, parameters, access modifiers (such as pulic or private), and implementation details (such as abstract or virtual. Use the getmethods or getmethod method of type to call a specific method.
(5) Use fiedinfo to learn the field name, access modifier (such as public or private), implementation details (such as static), and obtain or set the field value.
(6) Use eventinfo to learn about the event name, event handler data type, custom attributes, declaration type, and reflection type, and add or remove event handlers.
(7) Use propertyinfo to understand the attribute name, data type, declaration type, reflection type, read-only or writable status, and obtain or set the attribute value.
(8) Use parameterinfo to know the parameter name, data type, input parameter, output parameter, and the parameter location in the method signature.
The system. reflection. emit namespace class provides a special form of reflection that can be constructed at runtime.
Reflection can also be used to create an application called a type browser, allowing you to select a type and view information about the selected type.
In addition, JScript and other language compilers use reflection to construct symbol tables. Classes in the system. runtime. serialization namespace use reflection to access data and determine the fields to be permanently saved. classes in the system. runtime. remoting namespace use reflection indirectly through serialization.
Using system;
Using system. reflection;
Namespace reflectionexample
{
Class class1
{
[Stathread]
Static void main (string [] ARGs)
{
System. Console. writeline ("list all types in the assembly ");
Assembly A = assembly. loadfrom ("reflectionexample.exe ");
Type [] mytypes = A. gettypes ();
Foreach (type T in mytypes)
{
System. Console. writeline (T. Name );
}
System. Console. Readline ();
System. Console. writeline ("list all methods in helloworld ");
Type ht = typeof (helloworld );
Methodinfo [] MIF = Ht. getmethods ();
Foreach (methodinfo MF in MIF)
{
System. Console. writeline (MF. Name );
}
System. Console. Readline ();
System. Console. writeline ("instantiate helloworld and call sayhello method ");
Object OBJ = activator. createinstance (HT );
String [] S = {"zhenlei "};
Object objname = activator. createinstance (HT, S );
// Bindingflags flags = (bindingflags. nonpublic | bindingflags. Public |
// Bindingflags. Static | bindingflags. instance | bindingflags. declaredonly );
Methodinfo msayhello = Ht. getmethod ("sayhello ");
Msayhello. Invoke (OBJ, null );
Msayhello. Invoke (objname, null );
System. Console. Readline ();
}
}
}
Using system;
Namespace reflectionexample
{
/// <Summary>
/// Summary of helloworld.
/// </Summary>
Public class helloworld
{
String myname = NULL;
Public helloworld (string name)
{
Myname = Name;
}
Public helloworld (): This (null)
{
}
Public string name
{
Get
{Return myname ;}
}
Public void sayhello ()
{
If (myname = NULL)
System. Console. writeline ("Hello World ");
Else
System. Console. writeline ("hello," + myname );
}
}
}
3. Use reflection technology in design mode implementation
Reflection technology can simplify factory implementation.
(1) Factory method: The subclass name to be implemented can be passed to the factory method through reflection, so that class instantiation is not required in the subclass.
(2) Abstract Factory: Using Reflection can reduce subclass of abstract factory.
Using Reflection technology can simplify the complexity of Factory Code. In the. NET project, factories using reflection technology have basically replaced the factory method.
The reflection technology can greatly simplify the generation of objects and greatly affect the implementation of the following design patterns.
(1) command mode: You can use the command type name as a parameter to directly obtain the command instance and dynamically execute the command.
(2) metadata sharing mode: Using Reflection technology to instantiate the metadata sharing mode can simplify the metadata sharing factory.
4.
Reflection Overview
definition of reflection: ability to review metadata and collect information about its type. Metadata (the most basic data unit after compilation) is a lot of tables. When compiling an assembly or module, the compiler creates a class definition table and a field definition table, and a method definition table ,. System. the reflection namespace contains several classes that allow you to reflect (PARSE) the Code of these metabases
and reflection-related namespaces (we access reflection information through these namespaces):
system. reflection. memberinfo
system. reflection. eventinfo
system. reflection. fieldinfo
system. reflection. methodbase
system. reflection. constructorinfo
system. reflection. methodinfo
system. reflection. propertyinfo
system. type
system. reflection. assembly
Layered reflection model:
Note: There is a one-to-many relationship between layers.
Function of reflection:
1. You can use reflection to dynamically create instances of the type, bind the type to an existing object, or obtain the type from an existing object.
2. The application needs to load a specific type from a specific program set at runtime, so that reflection can be used for a task.
3. Reflection main applications and class libraries. These class libraries need to know a type definition to provide more functions.
Application highlights:
1. In real applications, few applications need to use the reflection type.
2. dynamic reflection binding sacrifices Performance
3. Some metadata information cannot be obtained through reflection.
4. Some reflection types are specifically used for the development and use of CLR development compilers, so you must realize that not all reflection types are suitable for everyone.
Assembly that reflects appdomain
When you need to reflect all the Assembly contained in the appdomain, the example is as follows:
Static void main
{
// Call all the assembly of appdomain through getassemblies
Foreach (Assembly assem in appdomain. currentdomain. getassemblies ())
{
// Reflect the information of the current Assembly
Reflector. reflectonassembly (assem)
}
}
Note: The getassemblies method of the appdomain object will return an array composed of system. reflection. Assembly elements.
Reflection of a single assembly
The above method is used to reflect all the assembly of the appdomain. We can display the call to one of the Assembly. The system. reflecton. assembly type provides the following three methods:
1. load Method: a highly recommended method. The load method carries an Assembly flag and loads it. Load will cause the CLR to apply the policy to the Assembly, which is successively in the global assembly buffer, find the Assembly under the application base directory and private path. If the Assembly cannot be found, the system throws an exception.
2. loadfrom method: Pass the path name (including the extension) of an assembly file. CLR loads the specified assembly. The passed parameter cannot contain any information about the version number, culture, and public key information. If the Assembly cannot be found in the specified path, an exception is thrown.
3. loadwithpartialname: never use this method, because the application cannot determine the version of the loaded assembly. The only purpose of this method is to help customers who use a certain behavior provided by the. NET Framework in the testing stage of the. NET Framework. This method will eventually be discarded.
Note: system. appdomain also provides a load method, which is different from the static load method of assembly. The load method of appdomain is an instance method, and a reference to the Assembly is returned, the static load of Assembly sends the Assembly value encapsulation back to the appdomain that sends the call. avoid using the appdomain load method whenever possible
Obtain type information using reflection
After talking about Assembly reflection, let's talk about the third layer in the reflection hierarchy model, type reflection.
A simple example of retrieving type information using reflection:
Using system;
Using sytem. reflection;
Class reflecting
{
Static void main (string [] ARGs)
{
Reflecting reflect = new reflecting (); // defines a new class.
// Call a reflecting.exe assembly
Assembly myassembly assembly.loadfrom(“reflecting.exe ")
Reflect. getreflectioninfo (myassembly); // gets the reflection Information
}
// Define a method to obtain the reflected content
Void getreflectioninfo (Assembly myassembly)
{
Type [] typearr = myassemby. gettypes (); // obtain the type
Foreach (type in typearr) // obtain detailed information for each type
{
// Obtain the structure information of the type
Constructorinfo [] myconstructors = type. getconstructors;
// Obtain the field information of the type.
Fieldinfo [] myfields = type. getfiedls ()
// Obtain method information
Methodinfo mymethodinfo = type. getmethods ();
// Obtain the Property Information
Propertyinfo [] myproperties = type. getproperties
// Obtain event information
Eventinfo [] myevents = type. getevents;
}
}
}
Other methods for getting type objects:
1. The system. Type parameter is of the string type. The full name of the type (including its namespace) must be specified for this string)
2. system. Type provides two instance methods: getnestedtype and getnestedtypes.
3. The instance methods provided by syetem. reflection. Assembly are GetType, gettypes, and getexporedtypes.
4. system. reflection. Moudle provides these instance methods: GetType, gettypes, findtypes
Set reflection type members
The member of the reflection type is the bottom layer of data in the reflection hierarchy model. We can use the getmembers method of the type object to obtain a type member. If we use getmembers without parameters, it only returns static variables and instance members of the public definition of this type, you can also use getmembers with parameters to return the specified type members through parameter settings. For more information about the parameters, see system. reflection. bindingflags Enumeration type in msdn.
For example:
// Set the member content of the type to be returned
Bindingflags BF = bingdingflags. declaredonly | bingdingflags. nonpublic | bingdingflags. Public;
Foreach (memberinfo mi int T. getmembers (BF ))
{
Writeline (MI. membertype) // output the specified type member
}
Create a type of instance through reflection
Through reflection, we can get the assembly type. We can create a new instance of this type based on the obtained assembly type. This is also the function of late binding when an object is created at runtime.
We can achieve this through the following methods:
1. createinstance method of system. activator. This method returns the reference of the new object. For more information, see msnd.
2. The createinstancefrom of system. activator is similar to the previous method, but the type and its assembly must be specified.
3. Method of system. appdomain: createinstance, createinstanceandunwrap, createappsancefrom and createappsacefromandunwrap
4. invokemember instance method of system. Type: This method returns a constructor that matches the input parameter and constructs this type.
5. system. reflection. constructinfo invoke instance method
Reflection interface
If you want to obtain a set of all interfaces inherited by the type, you can call findinterfaces getinterface or getinterfaces of the type. All these methods can only return directly inherited interfaces of this type. They do not return interfaces inherited from an interface. To return the basic interface, you must call the preceding method again.
Reflection performance:
When Using Reflection to call a type or trigger method, or when accessing a field or attribute, CLR needs to do more work: Check parameters, check permissions, and so on, so the speed is very slow. Therefore, do not use reflection for programming. You can use the following methods to write a dynamic Constructor (late binding:
1. inherit from the class. This type is derived from a known basic type during compilation. An instance of this type is generated at runtime, and its reference is placed in a variable of its basic type, then, call the virtual method of the basic type.
2. Implemented through interfaces. At runtime, construct an instance of this type, place its reference to a variable of its interface type, and then call the virtual method defined by this interface.
3. implement it through delegation. Let this type implement a method. Its name and prototype are consistent with a delegate that is known during compilation. Construct an instance of this type at runtime, then construct the instance of the delegate using the object and name of the method, and then call the method you want through the delegate. This method is more efficient than the previous two methods.