Reflection, c # reflection
1. What is reflection?
2. Relationships between namespaces and accessories
3. What is the purpose of obtaining type information during runtime?
4. How to Use reflection to obtain the type
5. How to dynamically create objects based on types
6. How to obtain methods and dynamic call Methods
7. dynamically create Delegation
1. What is reflection?
Reflection, which is translated into Reflection in Chinese.
This is.. Net ,. net applications are composed of several parts: 'assembly ', 'module', and 'Type (class) '. Reflection provides a programming method, this allows programmers to obtain relevant information about these components during the running period, for example:
The Assembly class can obtain information about running accessories, dynamically load the accessories, find the type information in the accessories, and create instances of this type.
The Type class can obtain the Type information of an object. This information includes all elements of the object, such as methods, constructors, and attributes. The Type class can obtain and call the information of these elements.
MethodInfo contains information about the method. You can use this class to obtain the name, parameter, and return value of the method and call it.
For example, FieldInfo and EventInfo are included in the System. Reflection namespace.
2. Relationships between namespaces and accessories
Many people may not be clear about this concept. It is necessary to clarify this concept for qualified. Net programmers.
The namespace is similar to a Java package, but it is not exactly the same, because the Java package must be placed according to the directory structure, and the namespace is not required.
The assemblies are the units where the .netapp executes. All the compiled .dllw..exe files are accessories.
The relationship between accessories and namespaces is not one-to-one and does not contain each other. One Accessory can have multiple namespaces, and one namespace can also exist in multiple accessories, this may be a bit vague. For example:
Assembly:
Namespace N1
{
Public class AC1 {...}
Public class AC2 {...}
}
Namespace N2
{
Public class AC3 {...}
Public class AC4 {...}
}
Assembly B:
Namespace N1
{
Public class BC1 {...}
Public class BC2 {...}
}
Namespace N2
{
Public class BC3 {...}
Public class BC4 {...}
}
Both of the accessories have two namespaces, N1 and N2, and each declares two classes. This is completely acceptable. Then we reference assembly A in an application, in this application, we can see that the classes below N1 are AC1 and AC2, And the classes below N2 are AC3 and ac4.
Then we remove the reference to A and add the reference to B, then the classes under N1 that we can see in this application become BC1 and BC2, and the same is true under N2.
If we reference these two accessories at the same time, we can see the following four classes in N1: AC1, AC2, BC1, and BC2.
Here, we can clearly understand a concept. The namespace only indicates the type of the family, such as the Han nationality and Hui nationality, and the accessories indicate the type of the family, for example, if someone lives in Beijing or Shanghai, then there are Han people in Beijing, Hui people in Shanghai, Han people in Shanghai, and Hui people. This is not a conflict.
As we have mentioned above, accessories are a place where the types reside. To use a class in a program, you must tell the compiler where the class lives before the compiler can find it, that is to say, the accessory must be referenced.
So when you write a program, you may not be sure where the class is, but you only know its name, can you use it? The answer is yes. This is reflection, that is, to provide this type of Address while the program is running, and find it.
If you are interested, let's take a look.
3. What is the purpose of obtaining type information during runtime?
Some people may wonder why the code can be written during development and is still executed at runtime, which is not only tedious but also inefficient.
This is a matter of opinion, just like early binding and late binding. Some people are opposed to late binding on the grounds of waste efficiency, but many people do not realize that they have used late binding when enjoying the benefits of virtual functions. This question is open. It's not clear in just a few words, so it's just a few minutes.
In my opinion, late binding can bring a lot of convenience in design. Proper use can greatly improve the reusability and flexibility of the program, but everything has two sides, it must be measured over and over again.
Next, what is the purpose of obtaining the type information during the runtime?
For example, many software developers prefer to leave some interfaces in their own software. Others can write some plug-ins to expand software functions. For example, I have a media player, I hope that the format of recognition can be easily extended in the future, so I declare an interface:
Public interface IMediaFormat
{
String Extension {get ;}
Decoder GetDecoder ();
}
This interface contains an Extension attribute, which returns a supported Extension, and another method returns a Decoder object (here I assume a Decoder class, this class provides the function of decoding the file stream, which can be derived from the extension plug-in). I can interpret the file stream through the decoder object.
In this case, all decoding plug-ins must derive a decoder and implement this interface. In the GetDecoder method, return the decoder object and configure its type name to my configuration file.
In this way, I do not need to know the type of the extended format when developing the player. I only need to obtain the type names of all decoder types from the configuration file, the dynamic creation of media format objects is used to convert them to the IMediaFormat interface.
This is a typical application of reflection.
4. How to Use reflection to obtain the type
First, let's look at how to obtain the type information.
There are two methods to obtain the type information. One is to obtain the instance object.
At this time, I only get this instance object. The method may be an object reference or an interface reference, but I don't know its exact type. I need to know, then you can call System. the GetType method declared on the Object to obtain the type Object of the Instance Object. For example, in a method, I need to determine whether the passed parameter has implemented an interface. If yes, then, a method of this interface is called:
...
Public void Process (object processObj)
{
Type t = processsObj. GetType ();
If (t. GetInterface ("ITest ")! = Null)
...
}
...
Another method to obtain the Type is to use the Type. GetType and Assembly. GetType methods, such:
Type t = Type. GetType ("System. String ");
Note that we have mentioned the relationship between namespaces and accessories. To find a class, you must specify its accessories, or call GetType on the obtained Assembly instance.
In this Assembly, only the type name can be written, and the other exception is mscorlib. dll, the type declared in this Assembly can also omit the Assembly name (. by default, mscorlib is referenced during the compilation of Net accessories. dll, unless it is explicitly specified during compilation), for example:
System. String is declared in mscorlib. dll. The above Type t = Type. GetType ("System. String") is correct.
System. Data. DataTable is declared in System. Data. dll, so:
Type. GetType ("System. Data. able") can only get null references.
Required:
Type t = Type. GetType ("System. Data. able, System. Data, Version = 1.0.3300.0, Culture = neutral, PublicKeyToken = b77a5c561934e089 ");
In this way, you can read the following post:
Http://expert.csdn.net/Expert/topic/2210/2210762.xml? Temp =. 1919977.
The answer from qqchen is wonderful.
5. How to dynamically create objects based on types
System. Activator provides methods to dynamically create objects based on types, such as creating a DataTable:
Type t = Type. GetType ("System. Data. able, System. Data, Version = 1.0.3300.0, Culture = neutral, PublicKeyToken = b77a5c561934e089 ");
DataTable table = (DataTable) Activator. CreateInstance (t );
Example 2: Create an object based on the parameter Constructor
Namespace TestSpace
{
Public class TestClass
{
Private string _ value;
Public TestClass (string value)
{
_ Value = value;
}
}
}
...
Type t = Type. GetType ("TestSpace. TestClass ");
Object [] constructParms = new object [] {"hello"}; // constructor Parameter
TestClass obj = (TestClass) Activator. CreateInstance (t, constructParms );
...
Put the parameters in an Object array in order.
6. How to obtain methods and dynamic call Methods
Namespace TestSpace
{
Public class TestClass {
Private string _ value;
Public TestClass (){
}
Public TestClass (string value ){
_ Value = value;
}
Public string GetValue (string prefix ){
If (_ value = null)
Return "NULL ";
Else
Return prefix + ":" + _ value;
}
Public string Value {
Set {
_ Value = value;
}
Get {
If (_ value = null)
Return "NULL ";
Else
Return _ value;
}
}
}
}
The above is a simple class that contains a constructor with parameters, a GetValue method, and a Value attribute. We can obtain and call the method by using the method name, for example:
// Obtain the type information
Type t = Type. GetType ("TestSpace. TestClass ");
// Parameters of the constructor
Object [] constuctParms = new object [] {"tietong "};
// Create an object based on the Type
Object dObj = Activator. CreateInstance (t, constuctParms );
// Obtain method information
MethodInfo method = t. GetMethod ("GetValue ");
// Some flag spaces of the call method. This field indicates Public and instance method, which is also the default value.
BindingFlags flag = BindingFlags. Public | BindingFlags. Instance;
// Parameters of the GetValue Method
Object [] parameters = new object [] {"Hello "};
// Call a method and use an object to receive the returned value
Object returnValue = method. Invoke (dObj, flag, Type. DefaultBinder, parameters, null );
Properties are similar to method calls. For details, refer to the MSDN
7. dynamically create Delegation
Delegate is the basis for implementing events in C #. Sometimes it is inevitable to dynamically create a Delegate. In fact, Delegate is also a type: System. Delegate. All delegates are derived from this class.
System. Delegate provides some static methods to dynamically create a Delegate, such as a Delegate:
Namespace TestSpace {
Delegate string TestDelegate (string value );
Public class TestClass {
Public TestClass (){
}
Public void GetValue (string value ){
Return value;
}
}
}
Example:
TestClass obj = new TestClass ();
// Obtain the type. In fact, you can use typeof to obtain the type.
Type t = Type. GetType ("TestSpace. TestClass ");
// Create a proxy, input the type, object for creating the proxy, and method name
TestDelegate method = (TestDelegate) Delegate. CreateDelegate (t, obj, "GetValue ");
String returnValue = method ("hello ");