protected override void LoadTargetArgument(PointCut pc, AdviceArgument parameter)
        {
            var targetFuncType = _ts.MakeGenericInstanceType(
                _ts.FuncGeneric2,
                _ts.ObjectArray,
                _ts.Object);

            var targetFuncCtor = targetFuncType.Resolve().Methods.First(m => m.IsConstructor && !m.IsStatic).MakeHostInstanceGeneric(targetFuncType);
            var targetMethod   = _wrapper.MakeCallReference(GetOrCreateUnwrapper().MakeHostInstanceGeneric(_target.DeclaringType));

            pc.ThisOrNull().Call(targetFuncCtor, args => args.Load(targetMethod));
        }
예제 #2
0
        protected override MethodDefinition FindOrCreateAfterStateMachineMethod()
        {
            var afterMethod = _stateMachine.Methods.FirstOrDefault(m => m.Name == Constants.AfterStateMachineMethodName);

            if (afterMethod == null)
            {
                var moveNext = _stateMachine.Methods.First(m => m.Name == "MoveNext");

                afterMethod = new MethodDefinition(Constants.AfterStateMachineMethodName, MethodAttributes.Private, _stateMachine.Module.ImportReference(StandardTypes.Void));
                afterMethod.Parameters.Add(new ParameterDefinition(_stateMachine.Module.ImportReference(StandardTypes.Object)));

                _stateMachine.Methods.Add(afterMethod);

                afterMethod.Mark(WellKnownTypes.DebuggerHiddenAttribute);
                afterMethod.Body.Instead(pc => pc.Return());

                VariableDefinition resvar = null;

                if (_asyncResult != null)
                {
                    resvar = new VariableDefinition(_asyncResult);
                    moveNext.Body.Variables.Add(resvar);
                    moveNext.Body.InitLocals = true;
                }

                var setResultCall    = _builder.Resolve().Methods.First(m => m.Name == "SetResult");
                var setResultCallRef = _asyncResult == null ? setResultCall : setResultCall.MakeReference(_builder);

                moveNext.Body.OnCall(setResultCallRef, il =>
                {
                    il = il.Prev();

                    var loadArg = new PointCut(args => args.Value(null));

                    if (_asyncResult != null)
                    {
                        il      = il.Store(resvar);
                        loadArg = new PointCut(args => args.Load(resvar).Cast(resvar.VariableType, StandardTypes.Object));
                    }

                    il = il.ThisOrStatic().Call(afterMethod.MakeReference(_stateMachine.MakeSelfReference()), loadArg);

                    if (_asyncResult != null)
                    {
                        il = il.Load(resvar);
                    }

                    return(il);
                });
            }

            return(afterMethod);
        }
예제 #3
0
        private void SetupEntryPoints()
        {
            if (_originalEntryPoint != null || _entryPoint != null)
            {
                throw new InvalidOperationException("Something went wrong");
            }

            _originalEntryPoint = TargetMethod.IsConstructor && !TargetMethod.IsStatic ?
                                  FindBaseClassCtorCall() :
                                  GetMethodOriginalEntryPoint();

            _entryPoint = OriginalEntryPoint.InsertBefore(OriginalEntryPoint.CreateInstruction(OpCodes.Nop));
        }
예제 #4
0
        public static PointCut CreateArray(this PointCut pc, TypeReference elementType, params Action <PointCut>[] elements)
        {
            pc = pc.Append(pc.CreateInstruction(OpCodes.Ldc_I4, elements.Length));
            pc = pc.Append(pc.CreateInstruction(OpCodes.Newarr, elementType));

            for (var i = 0; i < elements.Length; i++)
            {
                pc = pc.Append(pc.CreateInstruction(OpCodes.Dup));
                SetByIndex(pc, elementType, i, elements[i]);
            }

            return(pc);
        }
예제 #5
0
 private static void InjectInitialization(MethodDefinition initMethod,
                                          FieldReference field,
                                          PointCut factory
                                          )
 {
     initMethod.Body.AfterEntry(
         e => e
         .IfEqual(
             l => l.This().Load(field),
             r => r.Null(),                          // (this.)aspect == null
             pos => pos.This().Store(field, factory) // (this.)aspect = new aspect()
             )
         );
 }
예제 #6
0
        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);
            }
        }
예제 #7
0
        public static void OnLoadField(this MethodBody body, FieldReference field, PointCut pc, Instruction startingFrom = null)
        {
            var fieldDef = field.Resolve();

            if (fieldDef.IsStatic)
            {
                body.OnEveryOccasionOf(i =>
                                       (i.OpCode == OpCodes.Ldsfld || i.OpCode == OpCodes.Ldsflda) && i.Operand is FieldReference f && f.DeclaringType.Match(field.DeclaringType) && f.Resolve() == fieldDef
                                       , pc, startingFrom);
            }
            else
            {
                body.OnEveryOccasionOf(i =>
                                       (i.OpCode == OpCodes.Ldfld || i.OpCode == OpCodes.Ldflda) && i.Operand is FieldReference f && f.DeclaringType.Match(field.DeclaringType) && f.Resolve() == fieldDef
                                       , pc, startingFrom);
            }
        }
예제 #8
0
        protected virtual void LoadInjectionsArgument(PointCut pc, AdviceArgument parameter)
        {
            var elements = _injection.Triggers.Select <CustomAttribute, Action <PointCut> >(ca => il =>
            {
                var ctor = ca.Constructor.Resolve();
                void ctorParams(PointCut ilc) => ca.ConstructorArguments.Select(caa => ilc.Value(caa)).ToArray();
                il.Call(ctor, ctorParams);

                if (ca.Properties.Any() || ca.Fields.Any())
                {
                    var catype = ca.AttributeType.Resolve();

                    var attrvar = new VariableDefinition(_ts.Import(ca.AttributeType));
                    _target.Body.Variables.Add(attrvar);
                    _target.Body.InitLocals = true;

                    il.Store(attrvar);

                    foreach (var namedArg in ca.Properties)
                    {
                        var prop = catype.Properties.First(p => p.Name == namedArg.Name).SetMethod;

                        il.Load(attrvar);
                        il.Call(prop, ilp => ilp.Value(namedArg.Argument));
                    }

                    foreach (var namedArg in ca.Fields)
                    {
                        var field = catype.Fields.First(p => p.Name == namedArg.Name);

                        il.Load(attrvar);
                        il.Store(field, ilf => ilf.Value(namedArg.Argument));
                    }
                    il.Load(attrvar);
                }
            }
                                                                                            ).ToArray();

            pc.CreateArray(_ts.Attribute, elements);
        }
예제 #9
0
        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);
        }
예제 #10
0
 public static void OnStoreVar(this MethodBody body, VariableReference variable, PointCut pc, Instruction startingFrom = null)
 {
     body.OnEveryOccasionOf(i =>
                            ((i.OpCode == OpCodes.Stloc || i.OpCode == OpCodes.Stloc_S) && ((i.Operand is int n && n == variable.Index) || (i.Operand is VariableDefinition v && v.Index == variable.Index))) ||
                            (variable.Index == 0 && i.OpCode == OpCodes.Stloc_0) ||
                            (variable.Index == 1 && i.OpCode == OpCodes.Stloc_1) ||
                            (variable.Index == 2 && i.OpCode == OpCodes.Stloc_2) ||
                            (variable.Index == 3 && i.OpCode == OpCodes.Stloc_3)
                            , pc, startingFrom);
 }
예제 #11
0
        public static void OnEveryOccasionOf(this MethodBody body, Func <Instruction, bool> predicate, PointCut pc, Instruction startingFrom = null)
        {
            var insts = body.Instructions;
            var start = startingFrom == null ? 0 : insts.IndexOf(startingFrom);

            var icol = insts.Skip(start).ToArray();

            foreach (var curi in icol)
            {
                if (predicate(curi))
                {
                    new Cut(body, curi).Here(pc);
                }
            }
        }
예제 #12
0
        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);
        }
 protected abstract void InsertStateMachineCall(PointCut code);
 protected virtual void LoadTypeArgument(PointCut pc, AdviceArgument parameter)
 {
     pc.TypeOf(_target.DeclaringType);
 }
 protected virtual void LoadReturnTypeArgument(PointCut pc, AdviceArgument parameter)
 {
     pc.TypeOf(_target.ReturnType);
 }
예제 #16
0
 public static void AfterEntry(this MethodBody body, PointCut action)
 {
     new Cut(body, GetCodeStart(body))
     .Prev()
     .Here(action);
 }
예제 #17
0
 protected virtual void LoadTargetArgument(PointCut pc, AdviceArgument parameter)
 {
     pc.Null();
 }
 protected override void LoadReturnTypeArgument(PointCut pc, AdviceArgument parameter)
 {
     pc.TypeOf(_stateMachine.Interfaces.First(i => i.Name.StartsWith("IEnumerable`1")));
 }
 protected override void LoadReturnValueArgument(PointCut pc, AdviceArgument parameter)
 {
     pc.This();
 }
예제 #20
0
 protected override void LoadArgumentsArgument(PointCut pc, AdviceArgument parameter)
 {
     pc.Load(_wrapper.Parameters[0]);
 }
예제 #21
0
        public static Cut LoadAspect(this Cut cut, AspectDefinition aspect, MethodDefinition method, PointCut accessor)
        {
            FieldReference aspectField;

            if (method.IsStatic || aspect.Scope == Scope.Global)
            {
                aspectField = GetGlobalAspectField(aspect);
            }
            else
            {
                aspectField = GetInstanceAspectField(aspect, method.DeclaringType, cut);
                cut         = cut.Here(accessor);
            }

            return(cut.Load(aspectField));
        }
예제 #22
0
        public static void Append(this MethodBody body, PointCut action)
        {
            var cut = new Cut(body, entry: false, exit: true);

            cut.Here(action);
        }
 protected virtual void LoadAttributesArgument(PointCut pc, AdviceArgument parameter)
 {
     pc.Null();
 }
예제 #24
0
 protected virtual void LoadReturnValueArgument(PointCut pc, AdviceArgument parameter)
 {
     pc.Null();
 }
 protected virtual void LoadNameArgument(PointCut pc, AdviceArgument parameter)
 {
     pc.Value(_target.Name);
 }
예제 #26
0
        private void SetupTaskContinuation()
        {
            if (_returnPoint != null || _originalReturnPoint != null)
            {
                throw new InvalidOperationException("Something went wrong");
            }

            var helper = GetOrCreateHelperClass();

            var continuation = new MethodDefinition(
                string.Format(ContinuationMethodName, TargetMethod.Name),
                MethodAttributes.Assembly,
                TargetMethod.Module.TypeSystem.Void);

            helper.Methods.Add(continuation);

            var tcsType       = ModuleContext.TypeSystem.TaskCompletionGeneric.MakeGenericType(_completionResultType);
            var taskTypedType = continuation.Module.Import(_hasResult ? TargetMethod.ReturnType : ModuleContext.TypeSystem.Task);

            var taskParameter = new ParameterDefinition(null, ParameterAttributes.None, taskTypedType);

            continuation.Parameters.Add(taskParameter);

            var tcsField = new FieldDefinition(string.Format(ContinuationFieldName, TargetMethod.Name), FieldAttributes.Public, tcsType);

            helper.Fields.Add(tcsField);

            var proc = ILProcessorFactory.GetOrCreateProcessor(continuation.Body);
            var ret  = proc.Create(OpCodes.Ret);

            proc.Append(ret);

            var pointcut = new PointCut(proc, ret);

            pointcut.LoadParameterOntoStack(taskParameter);
            pointcut.InjectMethodCall(ModuleContext.TypeSystem.Task.Resolve().Properties.First(p => p.Name == "IsCompleted").GetMethod, new object[] { });

            pointcut.TestValueOnStack(true,
                                      doIfTrue: pc =>
            {
                pc.LoadParameterOntoStack(taskParameter);
                pc.InjectMethodCall(ModuleContext.TypeSystem.Task.Resolve().Properties.First(p => p.Name == "IsFaulted").GetMethod, new object[] { });
                pc.TestValueOnStack(false,
                                    doIfTrue: pct =>
                {
                    if (_hasResult)
                    {
                        _resultVar = pct.CreateVariable(_completionResultType,
                                                        loadData: c =>
                        {
                            c.LoadParameterOntoStack(taskParameter);
                            c.InjectMethodCall(taskTypedType.Resolve().Properties.First(p => p.Name == "Result").GetMethod.MakeGeneric(taskTypedType), new object[] { });
                        });
                    }

                    var syncReturnPc = pct.InsertBefore(pct.CreateInstruction(OpCodes.Nop));
                    _returnPoint     = new AsyncPointCut(_helperThisRefFiled, _helperArgumentsFiled, proc, syncReturnPc.InjectionPoint);

                    var setresultMethod = tcsType.Resolve().Methods.First(m => m.Name == "SetResult").MakeGeneric(tcsType);

                    pct.LoadSelfOntoStack();
                    pct.LoadField(tcsField);
                    pct.InjectMethodCall(setresultMethod, new object[] { _resultVar ?? Markers.DefaultMarker });
                });
            },
                                      doIfFalse: pc =>
            {
                var setresultMethod = tcsType.Resolve().Methods.First(m => m.Name == "SetResult").MakeGeneric(tcsType);

                pc.LoadSelfOntoStack();
                pc.LoadField(tcsField);
                pc.InjectMethodCall(setresultMethod, new object[] { Markers.DefaultMarker });
            });

            VariableDefinition taskResult = null;

            if (_isVoid)
            {
                taskResult = OriginalEntryPoint.CreateVariable(ModuleContext.TypeSystem.Task);
            }
            else
            {
                taskResult = OriginalEntryPoint.CreateVariable(TargetMethod.ReturnType);
            }

            var processor = ILProcessorFactory.GetOrCreateProcessor(TargetMethod.Body);

            var singleReturnPoint = processor.Create(OpCodes.Nop);

            _originalReturnPoint = new PointCut(processor, SetupSingleReturnPoint(processor.Create(OpCodes.Br, singleReturnPoint), taskResult)); //todo:: optimize

            if (_isVoid)
            {
                AsyncVoidRewriter.Rewrite(_originalReturnPoint, TargetMethod, taskResult);
            }

            processor.SafeAppend(singleReturnPoint);

            PointCut continuationPoint = null;

            if (!_isVoid)
            {
                continuationPoint = new PointCut(processor, processor.SafeAppend(processor.CreateOptimized(OpCodes.Ldloc, taskResult.Index)));
                processor.SafeAppend(processor.Create(OpCodes.Ret));
            }
            else
            {
                continuationPoint = new PointCut(processor, processor.SafeAppend(processor.Create(OpCodes.Ret)));
            }

            // var tcs = new TaskContinuationSource<TResult>();
            var tcsctor = tcsType.Resolve().Methods.First(m => m.IsConstructor && !m.IsStatic).MakeGeneric(tcsType);
            var tcsVar  = continuationPoint.CreateVariable(tcsType, null, c => c.InjectMethodCall(tcsctor));

            // var helper = new Helper();
            var helperVar = continuationPoint.CreateVariable(helper, null, c => c.InjectMethodCall(helper.Methods.First(m => m.IsConstructor && !m.IsStatic)));

            // var args = new object[] { param1, param2 ... };
            var argsvar = continuationPoint.CreateVariable(new ArrayType(TargetMethod.Module.TypeSystem.Object), null, c => c.LoadCallArgument(TargetMethod.Parameters.ToArray(), new ArrayType(TargetMethod.Module.TypeSystem.Object)));

            //helper.this_ref = this
            continuationPoint.LoadVariable(helperVar);
            continuationPoint.SetField(_helperThisRefFiled, c => c.LoadSelfOntoStack());

            // helper.args = args
            continuationPoint.LoadVariable(helperVar);
            continuationPoint.SetField(_helperArgumentsFiled, c => c.LoadVariable(argsvar));

            // helper.continuationSource = tcs
            continuationPoint.LoadVariable(helperVar);
            continuationPoint.SetField(tcsField, c => c.LoadVariable(tcsVar));

            // task.ContinueWith(new Action<TResult>(helper.Continuation))
            continuationPoint.LoadVariable(helperVar);
            continuationPoint.InsertBefore(continuationPoint.CreateInstruction(OpCodes.Ldftn, continuation));

            var actionTr       = continuation.Module.Import(ModuleContext.TypeSystem.ActionGeneric.MakeGenericType(taskTypedType));
            var contActionCtor = continuation.Module.Import(actionTr.Resolve().Methods.First(m => m.IsConstructor && !m.IsStatic))
                                 .MakeGeneric(actionTr);

            var actionVar = continuationPoint.CreateVariable(actionTr, null, c => c.InsertBefore(continuationPoint.CreateInstruction(OpCodes.Newobj, (MethodReference)c.CreateMemberReference(contActionCtor))));

            MethodReference contWithMethod = continuation.Module.Import(taskTypedType.Resolve().Methods.First(m => m.Name == "ContinueWith" && m.Parameters.Count == 1));

            if (_hasResult)
            {
                contWithMethod = contWithMethod.MakeGeneric(taskTypedType);
            }

            continuationPoint.LoadVariable(taskResult);
            continuationPoint.InjectMethodCall(contWithMethod, new object[] { actionVar });
            continuationPoint.InsertBefore(continuationPoint.CreateInstruction(OpCodes.Pop));

            // task = tcs.Task
            if (!_isVoid)
            {
                var getTask = continuation.Module.Import(tcsType.Resolve().Properties.First(p => p.Name == "Task").GetMethod)
                              .MakeGeneric(tcsType);

                continuationPoint.SetVariable(taskResult,
                                              c =>
                {
                    c.LoadVariable(tcsVar);
                    c.InjectMethodCall(getTask);
                });
            }
        }
 protected virtual void LoadReturnValueArgument(PointCut pc, AdviceArgument parameter)
 {
     _log.LogWarning(CompilationMessage.From($"Advice {_effect.Type.ToString()} does not support {parameter.Source.ToString()} argument and will always return null", _effect.Method));
     pc.Null();
 }
예제 #28
0
        public static void Rewrite(PointCut asyncVoidPc, MethodDefinition asyncVoidMethod, VariableDefinition taskVar)
        {
            asyncVoidMethod.Body.SimplifyMacros();

            var asyncVoidMBType = asyncVoidMethod.Module.Import(typeof(AsyncVoidMethodBuilder));
            var asyncTaskMBType = asyncVoidMethod.Module.Import(typeof(AsyncTaskMethodBuilder));

            asyncVoidMethod.Body.Variables.First(v => v.VariableType.IsTypeOf(asyncVoidMBType)).VariableType = asyncTaskMBType;

            Instruction    loadStateMachineInst = null;
            FieldReference builderField         = null;

            foreach (var inst in asyncVoidMethod.Body.Instructions)
            {
                var method = inst.Operand as MethodReference;

                if (method != null && method.DeclaringType.IsTypeOf(asyncVoidMBType))
                {
                    var newMethod = asyncVoidMethod.Module.Import(asyncTaskMBType.Resolve().Methods.First(m => m.Name == method.Name));

                    if (method.IsGenericInstance)
                    {
                        newMethod = newMethod.MakeGeneric(newMethod.DeclaringType, ((IGenericInstance)method).GenericArguments.ToArray());
                    }

                    inst.Operand = newMethod;

                    if (method.Name == "Create")
                    {
                        loadStateMachineInst = inst.Previous;
                        builderField         = (FieldReference)inst.Next.Operand;
                    }
                }
            }

            var stateMachine = builderField.DeclaringType.Resolve();

            stateMachine.Fields.First(v => v.FieldType.IsTypeOf(asyncVoidMBType)).FieldType = asyncTaskMBType;

            foreach (var md in stateMachine.Methods)
            {
                RewriteMethod(md);
            }

            var getTask = asyncTaskMBType.Resolve().Properties.First(p => p.Name == "Task").GetMethod;

            if (loadStateMachineInst == null || builderField == null)
            {
                throw new NotSupportedException("Unsupported state machine implementation");
            }

            asyncVoidPc.SetVariable(taskVar,
                                    c =>
            {
                c.InsertBefore(c.CreateInstruction(loadStateMachineInst.OpCode, (VariableDefinition)loadStateMachineInst.Operand));
                c.InsertBefore(c.CreateInstruction(OpCodes.Ldflda, builderField));
                c.InjectMethodCall(getTask);
            });

            asyncVoidMethod.Body.OptimizeMacros();
        }
 protected virtual void LoadMethodArgument(PointCut pc, AdviceArgument parameter)
 {
     pc.MethodOf(_target).Cast(_ts.MethodBase);
 }
예제 #30
0
 public static PointCut GetByIndex(this PointCut pc, TypeReference elementType, int index)
 {
     pc = pc.Append(pc.CreateInstruction(OpCodes.Ldc_I4, index));
     pc = pc.Append(pc.CreateInstruction(GetLoadOpcode(elementType)));
     return(pc);
 }