Exemplo n.º 1
0
        /// <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);
        }
Exemplo n.º 2
0
        /// <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);
            }
        }