private void SetupAroundInfrastructure() { TopWrapper = WrapOriginalMethod(); _lastWrapper = CreateUnwrapMethod(TopWrapper); var topWrapperCut = PointCut.FromEmptyBody(TopWrapper.Body, OpCodes.Ret); //var args = new object[]{ arg1, agr2 } var argsvar = topWrapperCut.CreateVariable(TypeSystem.ObjectArray, null, c => c.LoadCallArgument(TopWrapper.Parameters.ToArray(), TypeSystem.ObjectArray)); // ExecExternalWrapper var resultVar = topWrapperCut.CreateVariable(TypeSystem.Object, null, c => { c.LoadSelfOntoStack(); _topWrapperCallSite = c.InjectMethodCall(_lastWrapper, new object[] { argsvar }); }); //fill ref and out foreach (var param in TopWrapper.Parameters) { var index = TopWrapper.Parameters.IndexOf(param); // todo:: optimize and move to some syntax helper if (param.ParameterType.IsByReference) { topWrapperCut.LoadParameterOntoStack(param, param.ParameterType); topWrapperCut.LoadVariable(argsvar); topWrapperCut.InsertBefore(topWrapperCut.CreateInstruction(OpCodes.Ldc_I4, index)); topWrapperCut.InsertBefore(topWrapperCut.CreateInstruction(OpCodes.Ldelem_Ref)); var elementType = ((ByReferenceType)param.ParameterType).ElementType; topWrapperCut.BoxUnboxTryCastIfNeeded(TypeSystem.Object, elementType); topWrapperCut.SaveIndirect(elementType); } } if (TopWrapper.ReturnType != TypeSystem.Void) { topWrapperCut.LoadVariable(resultVar); topWrapperCut.BoxUnboxTryCastIfNeeded(TypeSystem.Object, TargetMethod.ReturnType); } }
public PointCut CreateNewAroundPoint() { if (_topWrapperCallSite == null) { SetupAroundInfrastructure(); } var newWrapper = CopyMethodDefinition(AroundWrappedMethodPrefix + _wrapperNo + "_" + TopWrapper.Name, TargetMethod.Attributes, TypeSystem.Object); newWrapper.NoInlining = false; MarkDebuggerHidden(newWrapper); MarkCompilerGenerated(newWrapper); TargetMethod.DeclaringType.Methods.Add(newWrapper); var argsParam = new ParameterDefinition(TypeSystem.ObjectArray); newWrapper.Parameters.Add(argsParam); var tempPc = PointCut.FromEmptyBody(newWrapper.Body, OpCodes.Ret); //if (_topWrapper.ReturnType == TypeSystem.Void) // tempPc.CreateVariableFromStack(TypeSystem.Object); //else if (_topWrapper.ReturnType.IsValueType) // tempPc.InsertBefore(tempPc.CreateInstruction(OpCodes.Box, TargetMethod.Module.Import(_topWrapper.ReturnType))); var newWapperPoint = new WrapperPointCut(argsParam, _lastWrapper, ILProcessorFactory.GetOrCreateProcessor(newWrapper.Body), newWrapper.Body.Instructions.First()); _lastWrapper = newWrapper; _wrapperNo++; //substiture top wrapper's call _topWrapperCallSite.InjectionPoint.Operand = newWrapper; return(newWapperPoint); }
private MethodDefinition CreateUnwrapMethod(MethodDefinition originalMethod) { var unwrapMethod = CopyMethodDefinition(AroundUnwrappedMethodPrefix + originalMethod.Name, originalMethod.Attributes, TypeSystem.Object); unwrapMethod.NoInlining = false; MarkDebuggerHidden(unwrapMethod); MarkCompilerGenerated(unwrapMethod); originalMethod.DeclaringType.Methods.Add(unwrapMethod); var argsParam = new ParameterDefinition(TypeSystem.MakeArrayType(TypeSystem.Object)); unwrapMethod.Parameters.Add(argsParam); var unwrapPoint = PointCut.FromEmptyBody(unwrapMethod.Body, OpCodes.Ret); unwrapPoint.LoadSelfOntoStack(); var vars = new List <VariableDefinition>(); foreach (var parameter in originalMethod.Parameters) { var varType = parameter.ParameterType; if (varType.IsByReference) { varType = ((ByReferenceType)varType).ElementType; } vars.Add( unwrapPoint.CreateVariable(varType, null, c => { c.LoadParameterOntoStack(argsParam); c.InsertBefore(c.CreateInstruction(OpCodes.Ldc_I4, originalMethod.Parameters.IndexOf(parameter))); c.InsertBefore(c.CreateInstruction(OpCodes.Ldelem_Ref)); c.BoxUnboxTryCastIfNeeded(TypeSystem.Object, varType); })); } foreach (var parameter in originalMethod.Parameters) { unwrapPoint.LoadVariable(vars[originalMethod.Parameters.IndexOf(parameter)], parameter.ParameterType); } unwrapPoint.InsertBefore(unwrapPoint.CreateInstruction(OpCodes.Call, TargetMethod.Module.Import(TargetMethod))); if (originalMethod.ReturnType == TypeSystem.Void) { unwrapPoint.LoadValueOntoStack <object>(null); } else if (originalMethod.ReturnType.IsValueType) { unwrapPoint.InsertBefore(unwrapPoint.CreateInstruction(OpCodes.Box, TargetMethod.Module.Import(originalMethod.ReturnType))); } foreach (var parameter in originalMethod.Parameters) { var index = originalMethod.Parameters.IndexOf(parameter); unwrapPoint.LoadParameterOntoStack(argsParam); unwrapPoint.InsertBefore(unwrapPoint.CreateInstruction(OpCodes.Ldc_I4, index)); unwrapPoint.LoadVariable(vars[index], TypeSystem.Object); unwrapPoint.InsertBefore(unwrapPoint.CreateInstruction(OpCodes.Stelem_Ref)); } return(unwrapMethod); }