示例#1
0
        /// <summary>
        /// Add switch registering to a class.
        /// </summary>
        /// <param name="clazz">The class to register switch.</param>
        /// <param name="context">The weaving context.</param>
        /// <param name="switchData">Data of switches.</param>
        /// <param name="statistics">Weaving statistics.</param>
        public static void Weave(TypeDefinition clazz, IWeavingContext context, IReadOnlyList <SwitchInitializingData> switchData, IClassWeavingStatisticsBuilder statistics)
        {
#if DEBUG
            if (clazz == null)
            {
                throw new ArgumentNullException("clazz");
            }

            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (switchData == null || !switchData.Any())
            {
                throw new ArgumentNullException("switchData");
            }

            if (statistics == null)
            {
                throw new ArgumentNullException("statistics");
            }
#endif
            var staticConstructor      = clazz.Methods.FirstOrDefault(mthd => mthd.IsStaticConstructor());
            MethodDefinition method    = null;
            ILProcessor      processor = null;
            if (staticConstructor == null)
            {
                method = new MethodDefinition(
                    ".cctor",
                    MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                    context.GetTypeReference(typeof(void)));
                processor = method.Body.GetILProcessor();
                method.Body.Instructions.Add(processor.Create(OpCodes.Ret));
                clazz.Methods.Add(method);
            }
            else
            {
                method    = staticConstructor;
                processor = method.Body.GetILProcessor();
            }

            var typeName     = clazz.GetFullName();
            var instructions = new List <Instruction>();
            foreach (var data in switchData)
            {
                RegisterSwitch(instructions, processor, context, data, typeName);
                statistics.AddSwitchWeavingRecord(StatisticsFactory.InitializeSwitchWeavingRecord(typeName, data.Property, data.MethodSignature, data.Aspect, data.Field.Name, data.Value));
            }

            CompleteSwitchRegistration(method, instructions, processor, context, typeName);
        }
示例#2
0
        private void CallAdvice(MethodDefinition method, ILProcessor processor, IAdviceInfo advice, List <Instruction> instructions, string propertyName, string methodSignature)
        {
            if (advice == null)
            {
                throw new ArgumentNullException("advice");
            }

            var pendingSwitchIndex    = context.PendingSwitchIndex;
            var firstIndex            = instructions.Count;
            var needContextVariable   = advice.ParameterFlag.Contains(AdviceParameterFlag.Context);
            var needExecutionVariable = advice.ParameterFlag.Contains(AdviceParameterFlag.Execution);
            var needReturnVariable    = advice.ParameterFlag.Contains(AdviceParameterFlag.Return);

            if (advice.IsSwitchedOn.HasValue)
            {
                var field = switchHandlerBuilder.GetSwitchField(
                    propertyName,
                    methodSignature,
                    advice.AspectName,
                    advice.IsSwitchedOn.Value);
                var index = context.GetLocalVariableForField(field);
                if (index < 0)
                {
                    index = method.Body.Variables.Count;
                    method.Body.Variables.Add(new VariableDefinition(context.GetTypeReference(typeof(bool))));
                    context.RecordLocalVariableForField(field, index);
                }

                if (needContextVariable)
                {
                    context.ExecutionContextSwitches.RegisterSwitch(index);
                }

                if (needExecutionVariable)
                {
                    context.ExecutionSwitches.RegisterSwitch(index);
                }

                if (needReturnVariable)
                {
                    context.ReturnSwitches.RegisterSwitch(index);
                }

                instructions.Add(processor.Create(OpCodes.Ldloc, index));

                // the null instruction is to be filled in later
                context.PendingSwitchIndex = instructions.Count;
                instructions.Add(null);
            }
            else
            {
                if (needContextVariable)
                {
                    context.ExecutionContextSwitches.SetUnSwitchable();
                }

                if (needExecutionVariable)
                {
                    context.ExecutionSwitches.SetUnSwitchable();
                }

                if (needReturnVariable)
                {
                    context.ReturnSwitches.SetUnSwitchable();
                }
            }

            if (needContextVariable)
            {
                instructions.Add(processor.Create(OpCodes.Ldloc, context.ExecutionContextVariableIndex));
            }

            if (needExecutionVariable)
            {
                instructions.Add(processor.Create(OpCodes.Ldloc, context.ExecutionVariableIndex));
            }

            if (advice.ParameterFlag.Contains(AdviceParameterFlag.Exception))
            {
                instructions.Add(processor.Create(OpCodes.Ldloc, context.ExceptionVariableIndex));
            }

            if (needReturnVariable)
            {
                instructions.Add(processor.Create(OpCodes.Ldloc, context.ReturnVariableIndex));
            }

            if (advice.ParameterFlag.Contains(AdviceParameterFlag.HasException))
            {
                instructions.Add(processor.Create(OpCodes.Ldloc, context.HasExceptionVariableIndex));
            }

            instructions.Add(processor.Create(OpCodes.Call, context.GetMethodReference(advice.Advice)));

            // apply switch from last advice call
            if (pendingSwitchIndex >= 0)
            {
                // here brfalse_S is safe, considering only several instructions are inserted after break instruction.
                instructions[pendingSwitchIndex] = processor.Create(OpCodes.Brfalse_S, instructions[firstIndex]);

                // reset pending switch index if no switch this time
                if (!advice.IsSwitchedOn.HasValue)
                {
                    context.PendingSwitchIndex = -1;
                }
            }
        }