Reflection and code transmission using DOT NET technology
Dynamic degradation or synchronization interface package
1 technical background
How to make the program really dynamically moved in the era of "dynamic".
In Java's structure we saw a java.lang.reflect package, starting to allow the program to understand the structure of the program. Then see AssemblyBuilder, ModuleBuilder, TypeBuilder, and other * Builder as the SYSTEM.REFLECTION name space as a Java's Wonderland Dot Net Framework, and the program can construct the program structure. We have entered the era of real dynamic use.
Recall, how fascinating! Let's run dynamically generated code. If you are not running the code loaded on the hard disk, how big is it!
1.1 reflection
Reflection is an extremely important part of object-oriented technology in the DOT NET framework. It is done by all classes in the System.Type class and the System.Reflection namespace and its subcare. The instance of the instance of the root Object of all classes GetType () can obtain the Type class instance of the class information of the instance.
The reflective function allows the program to understand the means of its own structure, in addition to providing a path of dynamic construction assemblies, modules, class (TYPE) structures, making the original zombie program have vitality. Reflection makes the program access program structure and constructs the program structure. Reflection is also known as RETROSPECTION, can also be translated into "self-province" or "reflection".
1.2 code transmission
The code transmission is running the operation code and parameters to the method constructor to make the final implementation of the dynamic generation class. Then you can use the required code structure.
Reflection transmission is a powerful technique for "sending" opcode. Although today's compiler is very fast, the speed of memory and processor is also sufficient, but it is really a gratifying thing when it is necessary to touch such a part of the core.
2 Degradation and synchronization theory
2.1 degradation
The object-oriented inheritance polymorphism causes the programming model to exhibit an extended divergence structure, which will only use the part of the function (herein the general referring to the Method), and the DOT NET also includes attributes. (Property) and events (event). Then you have an exception or not any action for other parts. The degradation occurs, which is part of a part of the function. For example:
l Sysetm.collections.ilist's C # language statement:
Public Interface IList: iCollection, IEnumerable
{
INT Add (Object Value);
Void clear ();
Bool Contains; Object Value;
INT INDEXOF (Object Value);
Void Insert (int index, object value);
Void Remove (Object Value);
Void Removeat (INT INDEX);
Bool isfixedsize {get;}
Bool isreadonly {get;}
Object this [int index] {get; set;}
}
To implement the read only of the above IList interface, it is required to deactivate Add, Clear, INSERT, REMOVE, REMOVEAT, THIS [] {set;} in a read-only derived class, and isreadOnly Returns constant True. However, this is just that the rule of the document cannot guarantee that an instance that returns isreadonly is inevitable to deaged. Such degradation is only the agreement within the document, but should be constrained. The means of standard degradation packages are introduced in the back dynamic packaging.
2.2 synchronization
Implementing the synchronous packaging generally rewrites all methods of the class or interface to be packaged, and the rewrite the template is as follows:
Public override returntype a_method ()
{
LOCK (this._syncroot)
Return this._target.a_method ();
}
Before and after calling, the synchronization operation is to enter the object and exit object. The class that is implemented is a synchronized package for an original or interface. This is not described here to apply if it is often used in multi-threaded applications.
3 Dot Net Framework Degeneration and Synchronized Package Realization
The READONLYLIST class is a private nested class for the Sysetm.Collections.ArrayList class, which is a ReadOnly degradation package for the ILIST interface.
The SYNCLIST class is a private nested class for the SYSETM.COLLECTIONS.ArrayList class, which is a synchronization package for the ILIST interface.
The two static methods passing can obtain the corresponding package example, the following is the associated portion C # declaration:
l ARRAYLIST class summary statement:
Public Class ArrayList: IList, Icollection, Ienumerable, Icloneable
{
......
Private Class ReadonlyList: ILIST
{...}
Private class syncilist: ilist
{...}
Public Static IList Readonly (IList List)
{
IF (List == Null)
Throw new argumentnullexception ("list");
Return New ArrayList. ReadonlyList (List);
}
Public Static IList Synchronized (IList List)
{
IF (List == Null)
Throw new argumentnullexception ("list");
Return new arraylist.syncilist (list);
}
}
l ReadonlyList class summary:
Private Class ReadonlyList: ILIST
{
INTERNAL READONLYLIST (ILIST L)
{
THIS._LIST = L;
}
Private ilist _list;
// Degradation method implementation
Public Virtual Int Add (Object Obj)
{
Throw new NotSupportedException ("NotSupported");
}
......
// Realization of non-degenerative methods
Public Virtual Bool Contains (Object Obj)
{
Return this._list.contains (OBJ);
}
......
Public Virtual Bool IsReadonly
{
get
{
Return True;
}
}
......
}
Degradation method such as ADD, released abnormalities. Non-degraded methods such as Contains, directly call. Only IsReadonly special handle returns True.
l Summary of the SyncList class:
Private class syncilist: ilist
{
Internal Syncilist (IList List)
{
THIS._LIST = List;
THIS._ROOT = List.syncroot;
}
Private ilist _list;
Private Object _root;
Public Virtual Int Add (Object Value)
{
LOCK (this._root)
Return this._list.add (value);
}
......
Public Virtual Bool Issynchronized
{
get
{
Return True;
}
}
......
Public Virtual Object Syncroot
{
get
{
Return THIS._ROOT;
}
}
}
Synchronization processing all methods such as add. Only Issynchronized special handle returns true, Syncroot special processing returns an asynchronous root input when initialization.
4 Dynamic Packaging Model
4.1 Disadvantages of the original mode
It can be seen from the implementation method in the DOT NET framework above that the corresponding class implementation is written for an interface that needs to be encapsulated. That is, it is necessary to write code according to the degraded or synchronized mode. It can be seen that the amount of information in the code is so small, it can be said that writing such a code is the sorrow of the programmer.
The first principle of programmers, all repetitive operations let the program do. If the programmer manually do this is not only tortured, but it is destroyed the rigor structure of the program. In this way, the error is easy to appear, the program readability is reduced, and the code is redundant.
So the class generated in accordance with the above mode should be implemented by the program, and someone will automatically generate code with text processing, but this is not our ultimate goal. We are just a class structure inherited to correspond to the corresponding interface, but it is not sensitive to the specific class name, but we need him to have a global unique, so that it is convenient next time. So if you rely on generating code, he cannot create an instance in a standard library as a common standard.
Objective speaking, the interface declared anywhere should have its only corresponding package implementation. Instead of writing a different implementation by different programmers, it is not possible to give a standard package check.
4.2 Ideal Package Model
l Global Packaging Boxer Class C # Language Package Some Declaration:
Public Sealed Class Boxer
{
Public Static Object Degenerate (Object Target, Type InterfacePe, IDEgenerateProvider DP);
Public Static Object Degenerate (Object Target, Type InterfaType, Type DegeneratettributeType);
Public Static Object Synchronize (Object Target, Type Interfacepe);
Public Static Object Synchronize (Object Target); Object SyncRoot
......
}
We can obtain an exemplary embodiment of the specified degradation method of any interface through the first two static methods. Asynchronous packages of any interface can also be obtained by the latter two static methods.
l IdegenerateProvider interface C # language complete statement:
Public interface ideGenerateProvider {
DegenerationTargets NeeddeGenerate (EventInfo EVN);
Bool Needdegenerate (MethodInfo Method);
DegenerationTargets Needdegenerate (PropertyInfo Property);
}
Provides an interface to judge whether or not the determination method is determined. Degradation needs to provide such a supplier instance.
l Boxer Class C # Language Package Check Some Declaration:
Public Sealed Class Boxer
{
Public Static Bool IsdeGenerated (Object Target, IDEGenerateProvider DP);
Public Static Bool Isdegenerated (Object Target, Type DegenerateAttributeType);
Public Static Bool IsdeGenerated (Object Target, Type InterfacePe, IdegenerateProvider DP);
Public Static Bool Isdegenerated (Object Target, Type InterfaType);
Public Static Bool Issynchronized (Object Target);
Public Static Bool Issynchronized (Object Target);
Public Static Bool Issynchronized (Object Target, Type Interface ";
Public Static Bool IsSynchronized (Object Target, Type InterfacePE, Object Syncroot);
......
}
l DegenerateTribute Attribute Class and DegenerateTargets Class C # Language Statement:
Public Abstract Class DegenerateAttribute: Attribute
{
Protected DegenerateAttribute (): this (degenerationTargets.all) {}
Protected DegenerateAttribute (DegenerationTargets Targets)
{
THIS._TARGETS = Targets;
}
Public DegenerationTargets Targets {get {returnide this._targets;}}
Private readonly DegenerationTargets_targets;
Public Static IDEgenerateProvider getdeGenerateProvider (Type AttributeType);
INTERNAL CLASS DegenerateProvider: IDEGENERATEPROVIDER
{
Public DegenerateProvider (Type AttributeType);
......
}
}
[Serializable, Flags]
Public Enum DegenerationTargets
{
Method = 0x01,
Getter = 0x02,
SETTER = 0x04
Adder = 0x08,
REMOVER = 0x10,
Event = adder | remover,
Property = getter | setter, all = method | Event | Property,
None = 0,
}
DegenerateAttribute provides an abstract base class for all degraded custom properties, which derives the specific reader or events of a method for specifying degradation or a specific reader or event (Event). Given his class information can be an instance of the corresponding IDEgenerateProvider by its static functions and nested classes.
l The ideal adaptation to readom.
Public Interface IList: iCollection, IEnumerable
{
[ReadonlyDegenerate]
INT Add (Object Value);
[ReadonlyDegenerate]
Void clear ();
Bool Contains; Object Value;
INT INDEXOF (Object Value);
[ReadonlyDegenerate]
Void Insert (int index, object value);
[ReadonlyDegenerate]
Void Remove (Object Value);
[ReadonlyDegenerate]
Void Removeat (INT INDEX);
[ReadonlyDegenerate (DegenerateTagets.Setter)]
Object this [int index] {get; set;}
}
[Serializable, AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event]
Public Sealed Class ReadonlyDegenerateAttribute: DegenerateAttribute: DegenerateAttribute
{
Public retadonlyattribute ();
Public ReadonlyAttribute (DegenerationTargets Targets);
}
4.3 Advantages of Model
If you only implement a specified degradation of an interface manual code. Then the degradation of the inheritance interface of this interface will be made by many repetitions, such artificial code implementation will be inefficient. Then this degraded information should be identified in the interface statement, then such information is not only given to this interface, but also provides such degradation to the inheritance interface.
All interfaces objectively exist their degradation and synchronized interface packages, then such packaging classes should not be implemented by programmers, and there should be program dynamically generated.
5 How to send code to implement dynamic package classes
Under the guidance of degradation supplies, our degraded work knows those functions that should be called because the degradation should be called, and the synchronized package is unexpected, and each method has the same mode. Because this article is returned to the mode of dynamic packaging. The work of sending code is involved in the Microsoft Intermediate Language (MSIL), which is just a technology implementation, of course, we can implement it in other platforms that support reflex and code transmission. And it should be the part that should be provided in the standard library.
The following is a key part of the C # language implementation of the synchronization interface package:
Private Static Void ImplementMethodSync Invoke (Typebuilder TB, MethodInfo Mi, Fieldbuilder FB, Fieldbuilder RFB) {
Type [] TypeArray1 = Boxer.Paramstypes (mi.getParameters ());
Methodbuilder Builder1 = Tb.defineMethod (mi.Name, Boxer. InterfaceMethodttributes, Mi.Returntype, TypeArray1);
Ilgenerator generator1 = builder1.getilgenerator ();
Generator1.deClareLocal (TypeOf (Object));
/ / Apply a local memory space for the return value
IF (mi.returntype! = Typeof (void))
Generator1.deClareLocal (mi.returntype);
// Load synchronization root instance
Generator1.emit (opcodes.ldarg_0);
Generator1.emit (Opcodes.ldfld, RFB);
GENERATOR1.EMIT (OPCODES.DUP);
Generator1.emit (opcodes.stloc_0);
// Enter the synchronization zone
Generator1.emit (opcodes.call, boxer.threadEnterMethod);
/ / In order to ensure that the program is not jumped by the abnormality of the calling process, it is necessary to form a deadlock, you need TRY {} finally {} to exit synchronization
// try {
Generator1.beginexceptionblock ();
Generator1.emit (opcodes.ldarg_0);
/ / To call the load object
Generator1.emit (opcodes.ldfld, fb);
/ / Load all parameters
INT Num1 = TypeArray1.Length;
IF (Num1> 0)
{
Generator1.emit (opcodes.ldarg_1);
IF (Num1> 1)
{
Generator1.emit (opcodes.ldarg_2);
IF (Num1> 2)
{
Generator1.emit (opcodes.ldarg_3);
For (int Num2 = 4; NUM2 <= Num1; Num2 )
Generator1.emit (opcodes.ldarg_s, (byte) Num2);
}
}
}
//transfer
Generator1.emit (opcodes.callvirt, mi);
// Store return value
IF (mi.returntype! = Typeof (void))
Generator1.emit (opcodes.stloc_1);
//}
// finally {
Generator1.beginfinallyBlock ();
Generator1.emit (opcodes.ldloc_0);
Generator1.emit (opcodes.call, boxer.threadexitmeth;
//}
Generator1.EndexceptionBlock ();
// Load return value
IF (mi.returntype! = Typeof (void))
Generator1.emit (opcodes.ldloc_1);
Generator1.emit (opcodes.ret);
TB.DefineMethodoverride (Builder1, Mi);
}
Private Static Void ImplementInterface (Typebuilder TB, Type InterfacePe, Fieldbuilder FB) {
// Realize Methods
MethodInfo [] Infoarray1 = interfaces ();
For (int Num1 = 0; Num1 { MethodInfo Info1 = Infoarray1 [Num1]; Boxer.ImplementMethodSyncInvoke (TB, INFO1, FB, RFB); } // Implement Properties PropertyInfo [] Infoarray2 = InterfacePe.getProperties (); For (int Num2 = 0; Num2 { PropertyInfo info2 = infoarray2 [Num2]; MethodInfo info3 = info2.getgetMethod (true); IF (Info3! = NULL) Boxer.ImplementMethodSyncInvoke (TB, INFO3, FB, RFB); Info3 = info2.getSetMethod (TRUE); IF (Info3! = NULL) Boxer.ImplementMethodSyncInvoke (TB, INFO3, FB, RFB); } // Realize Events Eventinfo [] infoarray3 = interfaType.getevents (); For (int Num3 = 0; Num3 { EventInfo info4 = infoarray3 [Num3]; MethodInfo Info5 = Info4.GetaddMethod (True); IF (Info5! = NULL) Boxer.ImplementMethodSyncInvoke (TB, INFO5, FB, RFB); INFO5 = info4.getremovemethod (true); IF (Info5! = NULL) Boxer.ImplementMethodSyncInvoke (TB, INFO5, FB, RFB); } } INTERNAL Static Object INTERSYNCHRONIZE (Object Target, Type InterfacePe, Object Syncroot) { Object obj1; Lock (Boxer.SynchronizedTable) { // identify the structured function that has been generated for dynamic class ConstructorInfo info1 = (constructorinfo) Boxer.SynchronizedTable [InterfacePE]; IF (Info1 == Null) { TYPE [] TYPEARRAY1 = New Type [2] {interfaceType, TypeOf (Object)} TypeBuilder builder1 = Boxer.BoxerModuleBuilder.DefineType ( "BoxedClasses.Synchronized" ( Boxer.SynchronizedCount), TypeAttributes.Public); builder1.SetCustomAttribute (new CustomAttributeBuilder (Boxer.SynchronizedAttribute.Constructor, new object [0])); Builder1.AddinterfaceImplementation (InterfaType); // Construct field target Fieldbuilder Builder2 = Builder1.definefield (Boxer.FindName (InterfaType, "_Target "), InterfacePe, Boxer.Fieldtattribute; // Construct field syncroot Fieldbuilder Builder3 = Builder1.definefield (Boxer.FindName (InterfaType, "_Syncroot"), TypeOf (Object), Boxer.fieldattribute; // Structure unique construction method ConstructorBuilder Builder4 = builder1.defineconstructor (methodattributes.public, callingconventions.standard, TypeArray1); Ilgenerator generator1 = builder4.getilgenerator (); Generator1.emit (opcodes.ldarg_0); GENERATOR1.EMIT (OPCODES.CALL, BOXER.ObjectConstructor); Generator1.emit (opcodes.ldarg_0); Generator1.emit (opcodes.ldarg_1); Generator1.emit (opcodes.stfld, builder2); Generator1.emit (opcodes.ldarg_0); Generator1.emit (opcodes.ldarg_2); Generator1.emit (opcodes.stfld, builder3); Generator1.emit (opcodes.ret); Boxer.ImplementInterface (Builder1, InterfaType, Builder2, Builder3); TYPE [] TypeArray3 = interfactionpe.getInterface (); For (int Num1 = 0; NUM1 { TYPE TYPE1 = TYPEARRAY3 [Num1]; Boxer.ImplementInterface (Builder1, Type1, Builder2, Builder3); } // Add this instance to the global table for later Boxer.SynchronizedTable.Add (InterfaType, (Info1 = builder1.createType (). GetConstructor (TypeArray1)))))) } Object [] objarray1 = new object [2] {target, syncroot}; Obj1 = info1.invoke (Objarray1); } Return Obj1; } 6 The new grammar specification is shown by the .NET 2.0 basic class library, the degradation and synchronization here can also be made to make new syntax specifications for programmers calls. The following is a new grammar specification as a C # language. 6.1 synchronization We can get the corresponding synchronization class instance by keywords Synchronize and ON, get synchronous inspections via issynchronized, for example: IList list; Object syncroot; ...... // [] is an optional part IList slist = list synchronize ilist [on syncroot]; // Internal implementation = (ilist) Boxer.Synchronize (List [SyncRoot]); Bool issync = slist issynchronized ilist [on syncroot]; // Internal implementation = Boxer.issynchronized (slist [, syncroot]); 6.2 Degeneration We can get the degradation instance by keyword Degenerate and ON, get synchronous inspections via IsdeGenerated, for example: IList list; IDEGENERATEPROVIDER DegenerateProvider; ...... IList dlist = list degenerate ilist on typeof (readonlydegenerateAttribute); // Internal implementation = (ilist) Boxer.degenerate (List, TypeOf (ReadonlyDegenerateAttribute); IList Dlist1 = List Degenerate IList on DegenerateProvider; /// Internal implementation = (ilist) Boxer.degenerate (List, DegenerateProvider); Bool isdeg = dlist isdegenerated ilist on typeof (readonlydegenerateAttribute); // Internal implementation = (ilist) Boxer.Indegenerated (List, TypeOf (ReadonlyDegenerateAttribute); 6.3 Non-retreating interface package We can get interface package examples by keyword box, get synchronous inspections via IsBoxed, for example: IList list = new arraylist (); ...... IList blist = list box ilist; // Internal implementation = (ilist) Boxer.degenerate (List, TypeOf (NondegenerateAttribute); Bool isb = blist isboxed ilist; // Internal implementation = (ilist) Boxer.Indegenerated (List, TypeOf (NondegenerateAttribute);