The agent object is a key section of AOP dynamic interception. Below to analyze how agent objects are defined.
1. CreateProxyTypeinternal static Type CreateProxyType (Type [] interfaces, IMixin [] mixins) {// ... AssemblyName assemblyName = new AssemblyName (); assemblyName.Name = "DynamicAssemblyProxyGen";
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.Run);. // define the access mode to specify the name and dynamic assembly, where the assembly to establish the operating mode ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule (assemblyName.Name, true) // Define a dynamic module in the dynamic program set, and the second parameter emits symbol information.
TypeBuilder typeBuilder = moduleBuilder.DefineType ( "ProxyType", TypeAttributes.Public | TypeAttributes.Class, null, MergeTypes (interfaces, mixins)); // define a class type, such as public, and achieve all interfaces and interfaces mixins, // Mergetype is used to merge Interfaces and Mixins into a TYPE [].
Fieldbuilder Handlerfield = Generatefield (TypeBuilder, IINVOCATIONHandler); // Generate an IinvocationHandler field. It is equivalent to public IinvocationHandler Handler;
FieldBuilder mixinHandlerField = GenerateField (typeBuilder, mixinHandlerFieldName, typeof (IMixinInvocationHandler)); // IMixinInvocation generating a field equivalent public IMixinInvocationHandler mixinHandler;. FieldBuilder mixinsField = GenerateField (typeBuilder, "mixins", typeof (IMixin [])); // generated A iMixin [] field, equivalent to public immixin [] mixins;
ConstructorBuilder Constr = GenerateConstructor (TypeBuilder, Handlerfield, Mixinsfield, MixinHandlerfield); // Generate a constructor.
GenerateInterfaceImplementation (TypeBuilder, Interfaces, Handlerfield); // Generates an implementation section of the interface.
GenerateMixinImplementation (typeBuilder, mixins, mixinHandlerField, mixinsField);.. // create means for implementing the interface portion of the mixer} 2 GenerateConstructorprivate static ConstructorBuilder GenerateConstructor (TypeBuilder typeBuilder, FieldBuilder handlerField, FieldBuilder mixinsField, FieldBuilder mixinHandlerField) {ConstructorBuilder consBuilder = typeBuilder.DefineConstructor (MethodAttributes .Public, callingconventions.standard, new type [] {typeof (iinvocationhandler), typeof (iMixinivationHandler), typeof (iMixin [])}); // Defines a constructor, specifying method is modified as public, and the call is convention to be STANDARD. / / I am equivalent to public proxytype (IinvocationHandler, iMixinivationHandler MixinHandler, iMixin [] mixins; ilgenerator ilgenerator = consBuilder.getilGenerator (); // acquisition IL generator. Used to generate IL code.
Ilgenerator.emit (opcodes.ldarg_0); ilgenerator.emit (opcodes.call, typeof (object) .getconstructor (new type [0])); // call the default constructor of the Object type, equivalent to public proxytype (... : base () // handler ilgenerator.emit (opcodes.ldarg_0); ilgenerator.emit (opcodes.ldarg_1); ilgenerator.emit (opcodes.stfld, handlerfield); / / assigning the Handlerfield field, equivalent to this.Handler = handler; // mixinHandler ilGenerator.Emit (OpCodes.Ldarg_0); ilGenerator.Emit (OpCodes.Ldarg_2); ilGenerator.Emit (OpCodes.Stfld, mixinHandlerField); // for mixinHandlerField field assignment, equivalent to this.mixinHandler = mixinHandler ;
// mixins ilgenerator.emit (opcodes.ldarg_0); ilgenerator.emit (opcodes.ldarg_3); ilgenerator.emit (opcodes.stfld, mixinsfield); / / assignment to the Mixinsfield field, equivalent to this.mixins = Mixins
Ilgenerator.emit (opcodes.ret);
Return consBuilder;}
The construction method of the agent object is similar to:
public Class ProxyType: object interface, the interface mixer {private IInvocationHandler handler; private IMixinvocationHandler mixinHandler; private IMixin [] mixins; public public ProxyType (IInvocationHandler handler, IMixinInvocationHandler mixinHandler, IMixin [] mixins); {this.handler = handler; this. MixinHandler = MixinHandler; this.Mixins = mixins;} // ...}
3. Generate the implementation of the interface
static void GenerateInterfaceImplementation (TypeBuilder typeBuilder, Type [] interfaces, FieldBuilder handlerField) {foreach (Type inter in interfaces) {GenerateInterfaceImplementation (typeBuilder, inter, handlerField, null, -1);} // iterate through all interfaces.}
Private static void generatemixinimplement (Typein [] Mixins, FieldBuilder MixinHandlerfield, Fieldbuilder Mixinsfield) {if (mixins == null) return;
For (int i = 0; i Foreach (Type Inter in Interfaces) {GenerateInterfaceImplement (Typebuilder, Inter, MixinHandlerfield, Mixinsfield, i);}} // Traverse all mixer interface} Static void GenerateInterfaceImplement (Typebuilder Typebuilder, Type Inter, Fieldbuilder Handlerfield, Fieldbuilder Mixinsfield, int mixinposition) {// ... Type [] baseinterfaces = inter .findinterfaces (new typefilter (nofilterImpl), inter); generateInterfaceImplementation (TypeBuilder, BaseInterface, handlerfield); // This is a recursive process for traversing all interfaces. PropertyInfo [] properties = inter.GetProperties (); PropertyBuilder [] propertiesBuilder = new PropertyBuilder [properties.Length]; for (int i = 0; i // achieve .private static void GeneratePropertyImplementation (TypeBuilder typeBuilder, PropertyInfo property, ref PropertyBuilder propertyBuilder) {propertyBuilder = typeBuilder.DefineProperty (property.Name, property.Attributes, property.PropertyType, null) attribute; // be by calling method DefindProperty Generate an implementation of the properties. Method implemented .private static // void GenerateMethodImplementation (TypeBuilder typeBuilder, MethodInfo method, PropertyBuilder [] properties, Type inter, FieldBuilder handlerField, FieldBuilder mixinsField, int mixinPosition) {ParameterInfo [] parameterInfo = method.GetParameters (); // obtain parameters information. System.Type [] parameters = new system.type [parameterinfo.length]; for (int i = 0; i Parameters [i] = parameterInfo [i] .parameterType; } // Get the type of parameters. MethodAttributes atts = MethodAttributes.Public | MethodAttributes.Virtual; if (method.Name.StartsWith ( "set_") || method.Name.StartsWith ( "get_")) {atts = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.Virtual } // Specify the modification of the method. MethodBuilder methodBuilder = typeBuilder.DefineMethod (method.Name, atts, CallingConventions.Standard, method.ReturnType, parameters); // definition method .if (method.Name.StartsWith ( "set_") || method.Name.StartsWith ( " Get_ ")) {forEach (PropertyBuilder Property In Properties) {if (Property == Null) {Break;} if (! property.name.equals ( )))) {Continue;} IF (Methodbuilder.name.startSwith) {Property.setSetMethod (MethodBuilder); Break;} else {profrty.setgetMethod (MethodBuilder); Break;}} // If the method begins with SET_ or GET_, then Traverse all properties, set the SET / GET method for the attribute if the name is the same. WriteilFormethod (MethodBuilder, Parameters, Handlerfield, Mixinsfield, MixInPosition); // method IL code. The specific code implemented by the method, this is a key, interception and mixing should be handled here. Private Static Void WriteilFormethod (Methodbuilder Builder, System.Type [] Parameters, Fieldbuilder Handlerfield, Fieldbuilder Mixinsfield, Int MixInPosition) {Int ArrayPositionInstack = 1; Ilgenerator ilgenerator = builder.getilGenerator (); Ilgenerator.DeclareLocal (TypeF (MethodBase)); // Defines a local variable for a MothoDBase type. IF (Builder.Returntype! = typeof (void) {ilgenerator.deClareLocal (Builder.ReturNType); ArrayPositionInstack = 2;} // If there is a return value, define a local variable to save the return value. Ilgenerator.DeclareLocal (TypeOf (object [])); // Defines a partial change of an Object [] type. ilGenerator.Emit (OpCodes.Call, typeof (MethodBase) .GetMethod ( "GetCurrentMethod")); // call GetCurrentMethod method .ilGenerator.Emit (OpCodes.Stloc_0); ilGenerator.Emit (OpCodes.Ldarg_0); ilGenerator.Emit (OpCodes .Ldfld, handlerfield; // this ilgenerator.emit (opcodes.ldarg_0); //Method base ilgenerator.emit (opcodes.ldloc_0); // mixin if (mixinPosition> -1) {ilgenerator.emit (opcodes.ldarg_0); ilgenerator.emit (opcodes.ldfld, mixinsfield; ilgenerator.emit); ilgenerator.emit (Opcodes. LDC_I4, MixInPosition; Ilgenerator.emit (opcodes.ldelem_ref); // arguments ilgenerator.emit (opcodes.ldc_i4, parameters.Length); Ilgenerator.emit (Opcodes.newarr, TypeOf (Object)); IF (parameters.length! = 0) {ilgenerator.emit (opcodes.stloc, arraypositionInstack; ilgenerator.emit (opcodes.ldloc, arraypositioninstack);} For (int C = 0; C Ilgenerator.emit (opcodes.ldc_i4, c); Ilgenerator.emit (Opcodes.ldarg, C 1); IF (Parameters [C] .issvalueType) {ilgenerator.emit (opcodes.box, parameters [c] .underlyingsystemType);} Ilgenerator.emit (opcodes.stelem_ref); ilgenerator.emit (opcodes.ldloc, arraypositioninstack);} switch (handlerField.Name) {case mixinHandlerFieldName: {ilGenerator.Emit (OpCodes.Callvirt, typeof (IMixinInvocationHandler) .GetMethod ( "Invoke")); break;} default: {ilGenerator.Emit (OpCodes.Callvirt, typeof (IInvocationHandler) .GetMethod ("invoke")); Break;}} // is processed according to the name of the field. OpCodes.callvirtr is specified as later binding. // If the field belongs to a mixer interface, execute iMixinivationHandler.invoke, / / otherwise call IInvocationHandler.Invoke.if (builder.ReturnType = typeof (void)!) {if {ilGenerator.Emit (OpCodes.Castclass, builder.ReturnType) (builder.ReturnType.IsValueType!);} else {ilGenerator.Emit (OpCodes.Unbox , builder.returntype; ilgenerator.emit (convertTyPetoPcode (Builder.Returntype);} Ilgenerator.emit (opcodes.stloc, 1); Label label = ilgenerator.defineLabel (); ilgenerator.emit (opcodes.br_s, label); Ilgenerator.markLabel (Label); Ilgenerator.emit (Opcodes.ldloc, 1);} else {ilgenerator.emit (opcodes.pop); } Ilgenerator.emit (opcodes.ret);} // Don't be very familiar with IL, some details are not clear. His friends who are familiar with IL will be corrected and supplemented.