Home  >  Article  >  Backend Development  >  C# Learning Reflection

C# Learning Reflection

巴扎黑
巴扎黑Original
2016-12-20 17:18:171262browse

1. What is reflection:
Reflection, Chinese translation is reflection.
This is the way to obtain runtime type information in .Net. .Net applications are composed of several parts: 'Assembly', 'Module', 'Type', and reflection provides A programming method that allows programmers to obtain relevant information about these components while the program is running.

Overview of Reflection

Definition of Reflection: The ability to examine metadata and gather type information about it. Metadata (the most basic data unit after compilation) is a large number of tables. When compiling an assembly or module, the compiler will create a class definition table, a field definition table, a method definition table, etc. The System.reflection namespace contains several classes that allow you to reflect (parse) the code of these metadata tables.


2. Specific uses of reflection:

(1) Use Assembly to define and load an assembly, load modules listed in the assembly manifest, and find types from this assembly and create instances of that type.
(2) Use Module to understand the assembly containing the module and the classes in the module. You can also 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 constructor. Use the Type's GetConstructors or GetConstructor method to call a specific constructor.
(4) Use MethodInfo to understand the method’s name, return type, parameters, access modifiers (such as pulic or private) and implementation details (such as abstract or virtual), etc. Use the GetMethods or GetMethod method of Type to call a specific method.
(5) Use FiedInfo to understand the name of the field, access modifiers (such as public or private) and implementation details (such as static), etc., and get or set the field value.
(6) Use EventInfo to learn the name of the event, event handler data type, custom properties, declaration type and reflection type, etc., and add or remove event handlers.
(7) Use PropertyInfo to understand the name, data type, declaration type, reflection type, read-only or writable status of the attribute, etc., and get or set the attribute value.
(8) Use ParameterInfo to understand the parameter name, data type, whether it is an input parameter or an output parameter, and the position of the parameter in the method signature, etc.


3. Namespaces related to reflection:


System.Reflection.Assembly

System.Reflection.MemberInfo
System.Reflection.EventInfo
System.Reflection.FieldInfo
System.Reflection.MethodBase
System.Reflection. ConstructorInfo
System.Reflection.MethodInfo
System.Reflection.PropertyInfo
System.Type


4. Reflection hierarchical model:



Note: There is a one-to-many relationship between levels

The role of reflection:

1. You can use reflection to dynamically create instances of a 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 assembly at run time so that reflection can be used to achieve a certain task.
3. Reflection is mainly used with class libraries. These class libraries need to know the definition of a type in order to provide more functions.

Application Points:

1. There are very few applications in real applications that need to use reflection types
2. Using reflection dynamic binding requires sacrificing performance
3. Some metadata information cannot be obtained through reflection
4. Certain reflection types are designed specifically for use by those developing compilers for the CLR, so you should be aware that not all reflection types are suitable for everyone.

6. Practical application of reflection:

Reflect the assembly of appDomain

static void Main
{
// Call all assemblies of appDomain through GetAssemblies
foreach (Assembly assem in Appdomain.currentDomain.GetAssemblies())
{
// Reflect the information of the current assembly
reflector.ReflectOnAssembly(assem)
}
}

Description: Calling the GetAssemblies method of the AppDomain object will return an array composed of System.Reflection.Assembly elements.

Reflecting a single assembly

We can explicitly call one of the assemblies. The system.reflecton.assembly type provides the following three methods:

1. Load method: A highly recommended method. The Load method takes an assembly flag and loads it. Load will cause the CLR to apply the policy to the assembly, successively in the global assembly buffer, the application base directory and the private path. Find the assembly below. If the assembly is not found, the system throws an exception.
2. LoadFrom method: Pass the path name of an assembly file (including extension), and the CLR will load the assembly you specify. The parameter passed cannot contain any information about the version number, culture, and public key information. If The assembly cannot be found at the specified path and an exception is thrown.
3. LoadWithPartialName: Never use this method because the application cannot determine the version of the assembly being loaded. The only purpose of this method is to help customers who use certain behaviors provided by the .Net framework in the testing phase of the .Net framework, and this method will eventually be abandoned.
Note: system.AppDomain also provides a Load method, which is different from Assembly's static Load method. AppDomain's load method is an instance method and returns a reference to the assembly. Assembly's static Load method is Encapsulate the assembly by value and send it back to the calling AppDomain. Try to avoid using the load method of AppDomain

Use reflection to obtain type information

A simple example of using reflection to obtain type information:

using system;
using sytem. reflection;
class reflecting
{
static void Main(string[]args)
{
reflecting reflect=new reflecting();//Define a new self class
//Call a reflecting.exe assembly
assembly myAssembly = assembly.loadfrom("reflecting.exe")
reflect.getreflectioninfo(myAssembly);// Get reflection information
}
// Define a method to get reflection content
void getreflectioninfo(assembly myassembly)
{
type[] typearr= myassemby.Gettypes();//Get the type
foreach (type type in typearr)//Get detailed information for each type
{
//Get the structural information of the type
constructorinfo[] myconstructors=type.GetConstructors;
// Get the field information of the type
fieldinfo[] myfields=type.GetFiedls()
//Get the method information
MethodInfo myMethodInfo=type.GetMethods();
// Get the property information
propertyInfo[] myproperties=type.GetProperties
// Get event information
EventInfo[] Myevents=type.GetEvents;
}
}
}

Several other ways to get type objects:

1. The System.type parameter is a string type, and the string must specify the complete name of the type (including its namespace)
2. System.type provides two instance methods: GetNestedType, GetNestedTypes
3. The instance methods provided by the Syetem.Reflection.Assembly type are: GetType, GetTypes, GetExporedTypes
4. System.Reflection.Moudle provides these instance methods: GetType, GetTypes, FindTypes

Set the members of the reflection type

The members of the reflection type are the lowest layer of data in the reflection hierarchy model. We can obtain the members of a type through the GetMembers method of the type object. If we are using GetMembers without parameters, it only returns the publicly defined static variables and instance members of the type. We can also use GetMembers with parameters to return specified type members through parameter settings. For specific parameters, please refer to the detailed description of the 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 an instance of the type through reflection

The type of the assembly can be obtained through reflection, and we can create a new instance of the type based on the obtained assembly type. This It is also the function of creating objects at runtime to implement late binding mentioned earlier. We can achieve this through the following methods:

1. CreateInstance method of System.Activator. This method returns a reference to the new object.
2. System.Activator's createInstanceFrom is similar to the previous method, but requires specifying the type and its assembly.
3. System.Appdomain methods: createInstance, CreateInstanceAndUnwrap, CreateInstranceFrom and CreateInstraceFromAndUnwrap
4. InvokeMember instance method of System.type: This method returns a constructor that matches the passed parameters and constructs the type.
5. Invoke instance method of System.reflection.constructinfo

Reflection type interface

If you want to get a collection of all interfaces inherited by a type, you can call Type's FindInterfaces GetInterface or GetInterfaces. All these methods can only return interfaces that the type directly inherits, they will not return interfaces that inherit from an interface. To return the base interface of the interface the above method must be called again.

Performance of Reflection

During reflection, the CLR has to do more work: verifying parameters, checking permissions, etc., and the speed is very slow. Try not to use reflection for programming. For applications that plan to write a dynamically constructed type (late binding), the following methods can be used instead:

1. through class inheritance. Let the type be derived from a compile-time-known base type, create an instance of the type at runtime, put a reference to it in a variable of its base type, and then call the base type's virtual method.
2. Implemented through interfaces. At run time, you construct an instance of the type, place a reference to it in a variable of its interface type, and then call the virtual methods defined by the interface.
3. Achieved through delegation. Have the type implement a method whose name and prototype match a delegate known at compile time. Construct an instance of the type at runtime, then use the object and name of the method to construct an instance of the delegate, and then call the method you want through the delegate. Compared with the previous two methods, this method does more work and is less efficient.

Usage Notes:

1. Cross-assembly reflection

In development, we often encounter this situation. It is necessary to reflect the types in B.dll in A.dll. If you are not careful, it will A runtime error occurs. Regarding cross-assembly reflection, remember two points:
(1) If you use typeof and the compilation can pass, then cross-assembly reflection must run normally. It can be said that typeof supports strong typing. For example,

Type supType = typeof(EnterpriseServerBase.DataAccess.IDBAccesser);

If the current assembly does not add a reference to EnterpriseServerBase.dll, the compilation will report an error.

(2) If you use Type.GetType, the situation is more complicated. This is because Type.GetType is not strongly typed. The parameter of Type.GetType is a string. When the target type represented by string is not in the current assembly, Type.GetType will return null at runtime. The solution is: load the target assembly first, and then use the Assembly.GetType method. Such as

Assembly asmb = Assembly.LoadFrom("EnterpriseServerBase.dll") ;
Type supType = asmb.GetType("EnterpriseServerBase.DataAccess.IDBAccesser") ;

Note that when using Type.GetType, even if you add For references to EnterpriseServerBase.dll, Type.GetType("EnterpriseServerBase.DataAccess.IDBAccesser") will also return null. This is because Type.GetType will only perform a type search in the current assembly.

2. Determine whether the return type of a method is void during reflection

Type serviceType = typeof(T);
MethodInfo methodInfo = serviceType.GetMethod(methodName);
Determine whether methodInfo.ReturnType == typeof(void) is true That’s it.


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn