public InstructionBlockChain CallMethodWithLocalParameters(MethodDefinition method, MethodDefinition targetMethod, VariableDefinition caller, VariableDefinition resultVariable) { var chain = new InstructionBlockChain(); var variables = new List <VariableDefinition>(); var index = 0; foreach (var parameter in method.Parameters) { var argIndex = method.IsStatic ? index : index + 1; var push = _creator.LoadValueOnStackFromArguments(argIndex); chain.Add(new InstructionBlock("push" + index, push.ToList())); var variable = _creator.CreateVariable(parameter.ParameterType); variables.Add(variable); var assign = _creator.AssignValueFromStack(variable); chain.Add(assign); index++; } var type = FixTypeReference(targetMethod.DeclaringType); var targetMethodReference = FixMethodReference(targetMethod, type); var call = caller == null ? _creator.CallStaticMethod(targetMethodReference, resultVariable, variables.ToArray()) : _creator.CallInstanceMethod(targetMethodReference, caller, resultVariable, variables.ToArray()); chain.Add(call); return(chain); }
public void AddOnExceptionCall( NamedInstructionBlockChain createAspectInstance, InstructionBlockChain callAspectOnException, NamedInstructionBlockChain setMethodExecutionArgsExceptionFromStack) { // add leave _markLeaveTryBlock = _processor.Create(OpCodes.Leave, _markEnd2BeforeOnExitCall); _processor.InsertBefore(_markEnd2BeforeOnExitCall, _markLeaveTryBlock); // add catch handler after leave _markExceptionHandlerStart = _processor.Create(OpCodes.Nop); _processor.InsertAfter(_markLeaveTryBlock, _markExceptionHandlerStart); var current = setMethodExecutionArgsExceptionFromStack.InsertAfter(_markExceptionHandlerStart, _processor); current = AddCreateAspectInstance(createAspectInstance, current); current = callAspectOnException.InsertAfter(current, _processor); _markExceptionHandlerEnd = _processor.Create(OpCodes.Rethrow); _processor.InsertAfter(current, _markExceptionHandlerEnd); // add exception handler _methodBody.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch) { CatchType = setMethodExecutionArgsExceptionFromStack.TypeReference, TryStart = _markStart4BeforeRealBodyStartExceptionHandler, TryEnd = _markExceptionHandlerStart, HandlerStart = _markExceptionHandlerStart, HandlerEnd = _markExceptionHandlerEnd.Next }); }
public InstructionBlockChain CallMethodWithReturn(MethodReference method, ILoadable instance, IPersistable returnValue, params ILoadable[] arguments) { var type = FixTypeReference(method.DeclaringType); method = FixMethodReference(type, method); InstructionBlock block; if (method.Resolve().IsStatic) { block = _creator.CallStaticMethod(method, returnValue, arguments); } else { block = _creator.CallInstanceMethod(method, instance, returnValue, arguments); } var chain = new InstructionBlockChain(); chain.Add(block); return(chain); }
public InstructionBlockChain CreateReturn() { var chain = new InstructionBlockChain(); chain.Add(new InstructionBlock("Return", _creator.CreateReturn())); return(chain); }
public void Add(InstructionBlockChain chain) { foreach (var block in chain.InstructionBlocks) { Add(block); } }
public void AddOnEntryCall( NamedInstructionBlockChain createAspectInstance, InstructionBlockChain callAspectOnEntry) { var current = AddCreateAspectInstance(createAspectInstance, _markStart3BeforeOnEntryCall); callAspectOnEntry.InsertAfter(current, _processor); }
public void AddOnExitCall( NamedInstructionBlockChain createAspectInstance, InstructionBlockChain callAspectOnExit, InstructionBlockChain setMethodExecutionArgsReturnValue) { var current = setMethodExecutionArgsReturnValue.InsertAfter(_markEnd2BeforeOnExitCall, _processor); current = AddCreateAspectInstance(createAspectInstance, current); callAspectOnExit.InsertAfter(current, _processor); }
private Instruction AddCreateAspectInstance(InstructionBlockChain createAspectInstance, Instruction current) { if (_aspectInstanceCreated) { return(current); } current = createAspectInstance.InsertAfter(current, _processor); _aspectInstanceCreated = true; return(current); }
public InstructionBlockChain LoadMethodExecutionArgsTagFromPersistable( IPersistable createMethodExecutionArgsInstance, IPersistable tag) { var setMethod = _referenceFinder.GetMethodReference(createMethodExecutionArgsInstance.PersistedType, md => md.Name == "set_MethodExecutionTag"); var chain = new InstructionBlockChain(); chain.Add(_creator.CallVoidInstanceMethod(setMethod, createMethodExecutionArgsInstance, tag)); return(chain); }
protected override void AddToSetup(InstructionBlockChain chain) { if (_setupPointer == null) { chain.Prepend(_ilProcessor); } else { chain.InsertAfter(_setupPointer, _ilProcessor); } _setupPointer = chain.Last; }
public void AddOnEntryCall( NamedInstructionBlockChain createAspectInstance, InstructionBlockChain callAspectOnEntry, InstructionBlockChain getSkipVar, NamedInstructionBlockChain conditionalExecutionInstance) { var current = AddCreateAspectInstance(createAspectInstance, _markStart3BeforeOnEntryCall); current = callAspectOnEntry.InsertAfter(current, _processor); current = getSkipVar.InsertAfter(current, _processor); current = conditionalExecutionInstance.InsertAfter(current, _processor); _processor.InsertAfter(current, _processor.Create(OpCodes.Brfalse, _markEnd2BeforeOnExitCall)); }
public InstructionBlockChain SetMethodExecutionArgsReturnValue( NamedInstructionBlockChain newMethodExectionArgsBlockChain, NamedInstructionBlockChain loadReturnValue) { var methodExecutionArgsSetReturnValueMethodRef = _referenceFinder.GetMethodReference(newMethodExectionArgsBlockChain.TypeReference, md => md.Name == "set_ReturnValue"); var callSetReturnValueBlock = _creator.CallVoidInstanceMethod(methodExecutionArgsSetReturnValueMethodRef, newMethodExectionArgsBlockChain.Variable, loadReturnValue.Variable); var block = new InstructionBlockChain(); block.Add(callSetReturnValueBlock); return(block); }
public InstructionBlockChain CallAspectOnExit(AspectData aspectData, IPersistable executionArgs) { var onExitMethodRef = _referenceFinder.GetMethodReference(aspectData.Info.AspectAttribute.AttributeType, md => md.Name == "OnExit"); var callOnExitBlock = _creator.CallVoidInstanceMethod(onExitMethodRef, aspectData.AspectPersistable, executionArgs); var callAspectOnExitBlockChain = new InstructionBlockChain(); callAspectOnExitBlockChain.Add(callOnExitBlock); return(callAspectOnExitBlockChain); }
public InstructionBlockChain CallAspectOnException(NamedInstructionBlockChain createAspectInstance, NamedInstructionBlockChain newMethodExectionArgsBlockChain) { var onExceptionMethodRef = _referenceFinder.GetMethodReference(createAspectInstance.TypeReference, md => md.Name == "OnException"); var callOnExceptionBlock = _creator.CallVoidInstanceMethod(onExceptionMethodRef, createAspectInstance.Variable, newMethodExectionArgsBlockChain.Variable); var callAspectOnExceptionBlockChain = new InstructionBlockChain(); callAspectOnExceptionBlockChain.Add(callOnExceptionBlock); return(callAspectOnExceptionBlockChain); }
public InstructionBlockChain CallAspectOnEntry(NamedInstructionBlockChain createAspectInstance, NamedInstructionBlockChain newMethodExectionArgsBlockChain) { var onEntryMethodRef = _referenceFinder.GetMethodReference(createAspectInstance.TypeReference, md => md.Name == "OnEntry"); var callOnEntryBlock = _creator.CallVoidInstanceMethod(createAspectInstance.Variable, onEntryMethodRef, newMethodExectionArgsBlockChain.Variable); var readParameterBlock = _creator.ReadParameterArray(newMethodExectionArgsBlockChain.Variable); var callAspectOnEntryBlockChain = new InstructionBlockChain(); callAspectOnEntryBlockChain.Add(callOnEntryBlock); callAspectOnEntryBlockChain.Add(readParameterBlock); return(callAspectOnEntryBlockChain); }
public InstructionBlockChain ReadReturnValue(IPersistable executionArgs, IPersistable returnValue) { if (InstructionBlockCreator.IsVoid(_method.ReturnType)) { return(new InstructionBlockChain()); } var getReturnValue = _referenceFinder.GetMethodReference(executionArgs.PersistedType, md => md.Name == "get_ReturnValue"); var readValueBlock = _creator.CallInstanceMethod(getReturnValue, executionArgs, returnValue); var readValueBlockChain = new InstructionBlockChain(); readValueBlockChain.Add(readValueBlock); return(readValueBlockChain); }
public InstructionBlockChain LoadExecuteBodyVariable(NamedInstructionBlockChain newMethodExecutionArgsBlockChain, out NamedInstructionBlockChain executeBodyVariable) { var getExecuteBody = _referenceFinder.GetMethodReference(newMethodExecutionArgsBlockChain.TypeReference, md => md.Name == "get_ExecuteBody"); var executeBodyVar = _creator.CreateVariable(getExecuteBody.ReturnType); executeBodyVariable = new NamedInstructionBlockChain(executeBodyVar, getExecuteBody.ReturnType); var block = _creator.CallInstanceMethod(newMethodExecutionArgsBlockChain.Variable, executeBodyVariable.Variable, getExecuteBody); var getExecuteBodyBlockChain = new InstructionBlockChain(); getExecuteBodyBlockChain.Add(block); return(getExecuteBodyBlockChain); }
protected override void WeaveMethodExecutionArgs(NamedInstructionBlockChain arguments) { var executionArgs = _creator.CreateMethodExecutionArgsInstance( arguments, _aspects[0].Info.AspectAttribute.AttributeType); _executionArgsField = _module.ImportReference(_stateMachine.AddPublicInstanceField(executionArgs.Variable.VariableType)); executionArgs.Add(new InstructionBlock("", Instruction.Create(OpCodes.Ldloc, executionArgs.Variable))); var field = new FieldPersistable(new VariablePersistable(_stateMachineLocal), _executionArgsField); var instructions = field.Store(executionArgs.Flatten(), _module.ImportReference(typeof(void))); var chain = new InstructionBlockChain(); chain.Add(instructions); AddToSetup(chain); ExecutionArgs = field; }
public InstructionBlockChain ReadReturnValue(NamedInstructionBlockChain newMethodExecutionArgsBlockChain, NamedInstructionBlockChain returnValue) { if (!_creator.HasReturnValue()) { return(new InstructionBlockChain()); } // VariableDefinition, VariableDefinition, MethodDefinition var getReturnValue = _referenceFinder.GetMethodReference(newMethodExecutionArgsBlockChain.TypeReference, md => md.Name == "get_ReturnValue"); var readValueBlock = _creator.CallInstanceMethod(newMethodExecutionArgsBlockChain.Variable, returnValue.Variable, getReturnValue); var readValueBlockChain = new InstructionBlockChain(); readValueBlockChain.Add(readValueBlock); return(readValueBlockChain); }
public override InstructionBlockChain CreateAspectInstance() { var aspectTypeReference = _module.ImportReference(Info.AspectAttribute.AttributeType); _aspectField = _module.ImportReference(_stateMachine.AddPublicInstanceField(aspectTypeReference)); var loadMachine = new VariablePersistable(_stateMachineLocal).Load(true); var newObjectAspectBlock = _creator.CreateAndNewUpAspect(Info.AspectAttribute); var loadOnStack = new InstructionBlock("Load on stack", Instruction.Create(OpCodes.Ldloc, newObjectAspectBlock.Variable)); var storeField = new InstructionBlock("Store Field", Instruction.Create(OpCodes.Stfld, _aspectField)); var newObjectAspectBlockChain = new InstructionBlockChain(); newObjectAspectBlockChain.Add(loadMachine); newObjectAspectBlockChain.Add(newObjectAspectBlock); newObjectAspectBlockChain.Add(loadOnStack); newObjectAspectBlockChain.Add(storeField); AspectPersistable = new FieldPersistable(new VariablePersistable(_stateMachineLocal), _aspectField); return(newObjectAspectBlockChain); }
public InstructionBlockChain CallOnExceptionInMoveNext(IPersistable executionArgs, VariableDefinition exceptionLocal) { var onExceptionMethodRef = _referenceFinder.GetMethodReference(Info.AspectAttribute.AttributeType, md => md.Name == "OnException"); var setMethod = _referenceFinder.GetMethodReference(executionArgs.PersistedType, md => md.Name == "set_Exception"); var setExceptionOnArgsBlock = _creator.CallVoidMethod(setMethod, GetMoveNextExecutionArgs(executionArgs), new VariablePersistable(exceptionLocal)); var sm = StateMachineFromMoveNext; var smPersistable = new ThisLoadable(sm); var aspectPersistable = new FieldPersistable(smPersistable, _aspectField.AsDefinedOn(sm)); var callOnExceptionBlock = _creator.CallVoidMethod(onExceptionMethodRef, aspectPersistable, GetMoveNextExecutionArgs(executionArgs)); var callAspectOnExceptionBlockChain = new InstructionBlockChain(); callAspectOnExceptionBlockChain.Add(setExceptionOnArgsBlock); callAspectOnExceptionBlockChain.Add(callOnExceptionBlock); return(callAspectOnExceptionBlockChain); }
private void AddToEnd(InstructionBlockChain chain) { chain.Append(_ilProcessor); }
protected virtual void WeaveOnException(IList <AspectData> allAspects, Instruction instructionCallStart, Instruction instructionCallEnd, Instruction instructionAfterCall, IPersistable returnValue) { var realInstructionAfterCall = instructionAfterCall ?? instructionCallEnd.Next; var tryLeaveInstruction = Instruction.Create(OpCodes.Leave, realInstructionAfterCall); _ilProcessor.InsertAfter(instructionCallEnd, tryLeaveInstruction); var exception = _creator.SaveThrownException(); var exceptionHandlerCurrent = exception.InsertAfter(tryLeaveInstruction, _ilProcessor); var pushException = _creator.LoadValueOnStack(exception); exceptionHandlerCurrent = pushException.InsertAfter(exceptionHandlerCurrent, _ilProcessor); var setExceptionFromStack = _creator.SetMethodExecutionArgsExceptionFromStack(ExecutionArgs); exceptionHandlerCurrent = setExceptionFromStack.InsertAfter(exceptionHandlerCurrent, _ilProcessor); var returnAfterHandling = new InstructionBlockChain(); if (returnValue != null) { returnAfterHandling.Add(returnValue.Load(false, false)); } returnAfterHandling.Add(new InstructionBlock("Return", Instruction.Create(OpCodes.Ret))); var indices = allAspects .Select((asp, index) => new { asp, index }) .Where(x => (x.asp.AspectMethods & AspectMethods.OnException) != 0) .Select(x => x.index) .Reverse() .ToList(); foreach (var index in indices) { var onExceptionAspect = allAspects[index]; if (HasMultipleAspects) { var load = _creator.LoadMethodExecutionArgsTagFromPersistable(ExecutionArgs, onExceptionAspect.TagPersistable); exceptionHandlerCurrent = load.InsertAfter(exceptionHandlerCurrent, _ilProcessor); } var callAspectOnException = _creator.CallAspectOnException(onExceptionAspect, ExecutionArgs); var nop = new InstructionBlock("Nop", Instruction.Create(OpCodes.Nop)); var callOnExitsAndReturn = new InstructionBlockChain(); for (var i = index - 1; i >= 0; --i) { var jthAspect = allAspects[i]; if ((jthAspect.AspectMethods & AspectMethods.OnExit) == 0) { continue; } if (HasMultipleAspects) { callOnExitsAndReturn.Add(_creator.LoadMethodExecutionArgsTagFromPersistable(ExecutionArgs, jthAspect.TagPersistable)); } callOnExitsAndReturn.Add(_creator.CallAspectOnExit(jthAspect, ExecutionArgs)); } if (returnValue != null) { callOnExitsAndReturn.Add(_creator.ReadReturnValue(ExecutionArgs, returnValue)); } callOnExitsAndReturn.Add(new InstructionBlock("Leave", Instruction.Create(OpCodes.Leave_S, returnAfterHandling.First))); callAspectOnException.Add(_creator.IfFlowBehaviorIsAnyOf(ExecutionArgs, nop.First, callOnExitsAndReturn, 1, 3)); callAspectOnException.Add(nop); callAspectOnException.InsertAfter(exceptionHandlerCurrent, _ilProcessor); exceptionHandlerCurrent = callAspectOnException.Last; } var flowBehaviorHandler = new InstructionBlockChain(); flowBehaviorHandler.Add(new InstructionBlock("throw", Instruction.Create(OpCodes.Rethrow))); flowBehaviorHandler.Add(new InstructionBlock("Leave", Instruction.Create(OpCodes.Leave_S, realInstructionAfterCall))); flowBehaviorHandler.InsertAfter(exceptionHandlerCurrent, _ilProcessor); returnAfterHandling.InsertAfter(flowBehaviorHandler.Last, _ilProcessor); _method.Body.ExceptionHandlers.Add(new ExceptionHandler(ExceptionHandlerType.Catch) { CatchType = _creator.GetExceptionTypeReference(), TryStart = instructionCallStart, TryEnd = tryLeaveInstruction.Next, HandlerStart = tryLeaveInstruction.Next, HandlerEnd = flowBehaviorHandler.Last.Next }); }
private void WeaveOnEntry(IPersistable returnValue) { var aspectsWithOnEntry = _aspects .Select((asp, index) => new { aspect = asp, index }) .Where(x => (x.aspect.AspectMethods & AspectMethods.OnEntry) != 0) .ToList(); foreach (var entry in aspectsWithOnEntry) { var aspect = entry.aspect; var call = _creator.CallAspectOnEntry(aspect, ExecutionArgs); AddToSetup(call); if (HasMultipleAspects) { AddToSetup(_creator.SaveMethodExecutionArgsTagToPersistable(ExecutionArgs, aspect.TagPersistable)); } var nopChain = new InstructionBlockChain(); nopChain.Add(new InstructionBlock(null, Instruction.Create(OpCodes.Nop))); var flowChain = new InstructionBlockChain(); var onExitChain = new InstructionBlockChain(); if (_method.ReturnType.IsByReference) { var notSupportedExceptionCtorString = _module.ImportReference( _creator.GetExceptionTypeReference <NotSupportedException>() .Resolve().Methods .FirstOrDefault(m => m.IsConstructor && m.Parameters.Count == 1 && m.Parameters[0].ParameterType.FullName == "System.String")); onExitChain.Add(new InstructionBlock("Throw NotSupported", Instruction.Create(OpCodes.Ldstr, "Weaving early return from a method with a byref return type is not supported."), Instruction.Create(OpCodes.Newobj, notSupportedExceptionCtorString), Instruction.Create(OpCodes.Throw))); } else { for (var i = entry.index - 1; i >= 0; --i) { var onExitAspect = _aspects[i]; if ((onExitAspect.AspectMethods & AspectMethods.OnExit) == 0) { continue; } if (HasMultipleAspects) { onExitChain.Add(_creator.LoadMethodExecutionArgsTagFromPersistable(ExecutionArgs, onExitAspect.TagPersistable)); } onExitChain.Add(_creator.CallAspectOnExit(onExitAspect, ExecutionArgs)); } } if (returnValue != null) { onExitChain.Add(_creator.ReadReturnValue(ExecutionArgs, returnValue)); onExitChain.Add(returnValue.Load(false, false)); } onExitChain.Add(new InstructionBlock("Return", Instruction.Create(OpCodes.Ret))); flowChain.Add(_creator.IfFlowBehaviorIsAnyOf(ExecutionArgs, nopChain.First, onExitChain, 3)); flowChain.Add(nopChain); AddToSetup(flowChain); } }
protected virtual void AddToSetup(InstructionBlockChain chain) { chain.Append(_ilProcessor); }
public InstructionBlockChain CallAspectOnException(NamedInstructionBlockChain createAspectInstance, NamedInstructionBlockChain newMethodExectionArgsBlockChain) { var onExceptionMethodRef = _referenceFinder.GetMethodReference(createAspectInstance.TypeReference, md => md.Name == "OnException"); var callOnExceptionBlock = _creator.CallVoidInstanceMethod(createAspectInstance.Variable, onExceptionMethodRef, newMethodExectionArgsBlockChain.Variable); var callAspectOnExceptionBlockChain = new InstructionBlockChain(); callAspectOnExceptionBlockChain.Add(callOnExceptionBlock); return callAspectOnExceptionBlockChain; }
public InstructionBlockChain SetMethodExecutionArgsReturnValue( NamedInstructionBlockChain newMethodExectionArgsBlockChain, NamedInstructionBlockChain loadReturnValue) { if (!_creator.HasReturnValue()) return new InstructionBlockChain(); var methodExecutionArgsSetReturnValueMethodRef = _referenceFinder.GetMethodReference(newMethodExectionArgsBlockChain.TypeReference, md => md.Name == "set_ReturnValue"); var callSetReturnValueBlock = _creator.CallVoidInstanceMethod(newMethodExectionArgsBlockChain.Variable, methodExecutionArgsSetReturnValueMethodRef, loadReturnValue.Variable); var block = new InstructionBlockChain(); block.Add(callSetReturnValueBlock); return block; }
public InstructionBlockChain IfFlowBehaviorIsAnyOf(Func <TypeReference, VariableDefinition> variableFactory, ILoadable args, Instruction nextInstruction, InstructionBlockChain thenBody, params int[] behaviors) { var typeRef = args.PersistedType.Resolve(); var getFlowBehavior = _referenceFinder.GetMethodReference(typeRef, m => m.Name == "get_FlowBehavior"); var flowBehaviorLocal = new VariablePersistable(variableFactory(_moduleDefinition.ImportReference(getFlowBehavior.ReturnType))); var flowBehaviorHandler = CallMethodWithReturn(getFlowBehavior, args, flowBehaviorLocal); if (behaviors.Length == 0) { return(flowBehaviorHandler); } for (var i = 0; i < behaviors.Length - 1; ++i) { flowBehaviorHandler.Add(flowBehaviorLocal.Load(false, false)); flowBehaviorHandler.Add(new InstructionBlock("FlowBehavior", Instruction.Create(OpCodes.Ldc_I4, behaviors[i]))); flowBehaviorHandler.Add(new InstructionBlock("If == then goto the 'then' block", Instruction.Create(OpCodes.Beq_S, thenBody.First))); } flowBehaviorHandler.Add(flowBehaviorLocal.Load(false, false)); flowBehaviorHandler.Add(new InstructionBlock("FlowBehavior", Instruction.Create(OpCodes.Ldc_I4, behaviors[behaviors.Length - 1]))); flowBehaviorHandler.Add(new InstructionBlock("If != then skip", Instruction.Create(OpCodes.Bne_Un, nextInstruction))); flowBehaviorHandler.Add(thenBody); return(flowBehaviorHandler); }
public InstructionBlockChain IfFlowBehaviorIsAnyOf(ILoadable args, Instruction nextInstruction, InstructionBlockChain thenBody, params int[] behaviors) { return(IfFlowBehaviorIsAnyOf(_creator.CreateVariable, args, nextInstruction, thenBody, behaviors)); }
protected override void WeaveOnException(IList <AspectData> allAspects, Instruction instructionCallStart, Instruction instructionCallEnd, Instruction instructionAfterCall, IPersistable returnValue) { var handler = _moveNext.Body.ExceptionHandlers.FirstOrDefault(IsStateMachineCatchBlock); if (handler == null) { throw new InvalidOperationException($"Async state machine for {_method.FullName} did not catch exceptions in the expected way."); } var exceptionLocal = handler.HandlerStart.GetLocalStoredByInstruction(_moveNext.Body.Variables); Instruction firstInstructionToSetException = GetFirstInstructionToSetException(handler, out var setResultMethod, out var loadBuilder); Instruction exceptionHandlerCurrent = firstInstructionToSetException.Previous; // Need to start inserting before SetException Instruction retInstruction = handler.HandlerEnd; var processor = _moveNext.Body.GetILProcessor(); Instruction gotoSetException = Instruction.Create(OpCodes.Br, firstInstructionToSetException); new InstructionBlock("else", gotoSetException).InsertAfter(exceptionHandlerCurrent, processor); // Need to replace leave.s with leave since we are adding instructions // between here and the destination which may invalidate short form labels. for (int i = 0; _moveNext.Body.Instructions[i] != handler.HandlerStart; ++i) { var inst = _moveNext.Body.Instructions[i]; if (inst.OpCode == OpCodes.Leave_S) { _moveNext.Body.Instructions.RemoveAt(i); _moveNext.Body.Instructions.Insert(i, Instruction.Create(OpCodes.Leave, inst.Operand as Instruction)); } } foreach (var onExceptionAspect in allAspects .Where(a => (a.AspectMethods & AspectMethods.OnException) != 0) .Reverse() .OfType <AspectDataOnAsyncMethod>()) { if (HasMultipleAspects) { var load = onExceptionAspect.LoadTagInMoveNext(ExecutionArgs); exceptionHandlerCurrent = load.InsertAfter(exceptionHandlerCurrent, processor); } var callAspectOnException = onExceptionAspect.CallOnExceptionInMoveNext(ExecutionArgs, exceptionLocal); if (setResultMethod.Parameters.Count == 1) { returnValue = new VariablePersistable(new InstructionBlockCreator(_moveNext, new ReferenceFinder(_module)).CreateVariable( ((GenericInstanceType)setResultMethod.DeclaringType).GenericArguments[0])); } var thenBody = new InstructionBlockChain(); if (setResultMethod.Parameters.Count == 1) { thenBody.Add(_creator.ReadReturnValue(onExceptionAspect.GetMoveNextExecutionArgs(ExecutionArgs), returnValue)); } thenBody.Add(loadBuilder.Clone()); if (setResultMethod.Parameters.Count == 1) { thenBody.Add(returnValue.Load(false)); } thenBody.Add(new InstructionBlock("Call SetResult", Instruction.Create(OpCodes.Call, setResultMethod))); thenBody.Add(new InstructionBlock("Leave peacefully", Instruction.Create(OpCodes.Leave, handler.HandlerEnd))); var nop = Instruction.Create(OpCodes.Nop); callAspectOnException.Add(_creator.IfFlowBehaviorIsAnyOf( new InstructionBlockCreator(_moveNext, new ReferenceFinder(_module)).CreateVariable, onExceptionAspect.GetMoveNextExecutionArgs(ExecutionArgs), nop, thenBody, 1, 3)); callAspectOnException.Add(new InstructionBlock("", nop)); callAspectOnException.InsertAfter(exceptionHandlerCurrent, processor); exceptionHandlerCurrent = callAspectOnException.Last; } }
public void Add(InstructionBlockChain chain) { foreach (var block in chain.InstructionBlocks) Add(block); }