/// <summary> /// Weave field into current aspect /// </summary> /// <param name="il">IL Generator</param> /// <param name="field">Field</param> /// <param name="fieldMethod">Field Method</param> private void BlockField(Mono.Cecil.Cil.ILProcessor il, Mono.Cecil.FieldDefinition field, MethodInfo fieldMethod) { var fieldName = field.Name; // Return if it is a backing field if (fieldName.IndexOf("k__BackingField") >= 0) { return; } var aspect = field.GetCustomAttribute <MemberInterceptionAspect>() ?? field.DeclaringType.GetCustomAttribute <MemberInterceptionAspect>() ?? field.DeclaringType.Module.Assembly.GetCustomAttribute <MemberInterceptionAspect>(); if (!ILWeaver.IsValidAspectFor(field, aspect)) { return; } var fieldType = field.FieldType; var isStatic = field.IsStatic; var fieldLocal = il.DeclareLocal(fieldType); var memberLocal = il.DeclareLocal(typeof(MemberContext)); var aspectField = ILWeaver.TypeFieldAspects[field.DeclaringType.FullName][aspect.GetType().FullName]; // Store current get field value il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, fieldLocal); // MemberContext(object instance, string locationName, object value) il.Emit(isStatic ? Mono.Cecil.Cil.OpCodes.Ldnull : Mono.Cecil.Cil.OpCodes.Ldarg_0); il.Emit(Mono.Cecil.Cil.OpCodes.Ldstr, fieldName); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, fieldLocal); if (fieldType.IsValueType) { il.Emit(Mono.Cecil.Cil.OpCodes.Box, fieldType); } il.Emit(Mono.Cecil.Cil.OpCodes.Newobj, MemberContextCtor); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, memberLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Ldsfld, aspectField); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, memberLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, fieldMethod); // Load value back to stack and reflect changes if any il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, memberLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, MemberContextValueMethod); // Convert to expected type il.Emit(fieldType.IsValueType ? Mono.Cecil.Cil.OpCodes.Unbox_Any : Mono.Cecil.Cil.OpCodes.Isinst, fieldType); }
/// <summary> /// Weave event invoke /// </summary> /// <param name="il">IL Generator</param> /// <param name="method">Method</param> /// <param name="field">Field</param> private void BlockInvokeEvent(Mono.Cecil.Cil.ILProcessor il, Mono.Cecil.MethodDefinition method, Mono.Cecil.FieldDefinition field) { var isStatic = method.IsStatic; var eventContext = il.DeclareLocal(typeof(EventContext)); var locals = new List <Mono.Cecil.Cil.VariableDefinition>(); var objLocal = il.DeclareLocal(typeof(object[])); var parameters = method.Parameters; var parameterLength = parameters.Count; var fieldDeclaringType = field.DeclaringType; var aspect = field.GetCustomAttribute <EventInterceptionAspect>() ?? fieldDeclaringType.GetCustomAttribute <EventInterceptionAspect>() ?? fieldDeclaringType.Module.Assembly.GetCustomAttribute <EventInterceptionAspect>(); if (!ILWeaver.IsValidAspectFor(field, aspect, allowEvents: true)) { return; } var aspectField = ILWeaver.TypeFieldAspects[fieldDeclaringType.FullName][aspect.GetType().FullName]; il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4, parameterLength); il.Emit(Mono.Cecil.Cil.OpCodes.Newarr, typeof(object)); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, objLocal); for (var i = 0; i < parameterLength; i++) { var parameter = parameters[i]; var parameterType = parameter.ParameterType; var local = il.DeclareLocal(parameterType); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, local); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, objLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4, parameterLength - i - 1); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, local); if (parameterType.IsValueType) { il.Emit(Mono.Cecil.Cil.OpCodes.Box, parameterType); } il.Emit(Mono.Cecil.Cil.OpCodes.Stelem_Ref); locals.Add(local); } if (!isStatic) { il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0); } il.Emit(Mono.Cecil.Cil.OpCodes.Ldnull); il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4, 1); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, objLocal); il.Emit(Mono.Cecil.Cil.OpCodes.Newobj, EventContextCtor); il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, eventContext); //InvokeEventMethod il.Emit(Mono.Cecil.Cil.OpCodes.Ldsfld, aspectField); il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, eventContext); il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, InvokeEventMethod); //Restore original invoke event parameters //locals.Reverse(); foreach (var local in locals) { il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, local); } }