Пример #1
0
        /// <summary>
        /// Weaves the call to the advice.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        /// <param name="filterAction">The filteraction.</param>
        /// <param name="parentType">The type containing the original method.</param>
        /// <param name="methodToCall">The advice method.</param>
        /// <param name="jpcVar">The local variable containing the JoinPointContext.</param>
        private static void CallAdvice(ICecilInliningInstructionVisitor visitor,
                                       FilterAction filterAction, TypeDefinition parentType, MethodReference methodToCall,
                                       VariableDefinition jpcVar)
        {
            // Place target on the stack:
            if (methodToCall.HasThis)
            {
                String fargTarget = getTarget(filterAction);
                if (fargTarget.Equals(FilterAction.InnerTarget) ||
                    fargTarget.Equals(FilterAction.SelfTarget))
                {
                    WeaveStrategyUtilities.LoadSelfObject(visitor, jpcVar);
                }
                else
                {
                    FieldDefinition target = parentType.Fields.GetField(fargTarget);
                    if (target == null)
                    {
                        throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                                  Properties.Resources.FieldNotFound, fargTarget));
                    }

                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This));
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldfld, target));
                }
            }

            // Load the JoinPointObject as the parameter
            if (methodToCall.Parameters.Count == 1)
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            }
            else if (methodToCall.Parameters.Count != 0)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                          Properties.Resources.AdviceMethodNotFound, getSelector(filterAction), getTarget(filterAction)));
            }

            // We can safely emit a callvirt here. The JITter will make the right call.
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, methodToCall));
        }
Пример #2
0
        /// <summary>
        /// Generate the code which has to be inserted at the place of the filter specified by the visitor.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        /// <param name="filterAction">The filter action.</param>
        /// <param name="originalCall">The original call.</param>
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            MethodReference methodToCall;

            // Get JoinPointContext
            VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal();

            // Get the methodReference
            MethodReference methodReference = (MethodReference)originalCall;
            TypeDefinition  parentType      = CecilUtilities.ResolveTypeDefinition(visitor.Method.DeclaringType);

            // Get method to call
            methodToCall = GetMethodToCall(visitor, filterAction, parentType);

            if (methodToCall == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                          Properties.Resources.AdviceMethodNotFound, getSelector(filterAction), getTarget(filterAction)));
            }

            // Set JoinPointContext
            WeaveStrategyUtilities.SetJoinPointContext(visitor, methodReference, filterAction);

            // Check if it is an innercall and set innercall context:
            if (getTarget(filterAction).Equals(FilterAction.InnerTarget))
            {
                WeaveStrategyUtilities.SetInnerCall(visitor, methodToCall);
            }

            // Do the advice-call
            AdviceActionWeaveStrategy.CallAdvice(visitor, filterAction, parentType, methodToCall, jpcVar);

            // Add nop to enable debugging
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Nop));
        }
Пример #3
0
        /// <summary>
        /// Generate the code which has to be inserted at the place of the filter specified by the visitor.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        /// <param name="filterAction">The filter action.</param>
        /// <param name="originalCall">The original call.</param>
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            // Get JoinPointContext
            VariableDefinition jpcVar = visitor.CreateJoinPointContextLocal();

            FieldDefinition target = null;

            // Get the methodReference
            MethodReference methodReference = null;

            TypeDefinition parentTypeDefinition = (TypeDefinition)(visitor.Method.DeclaringType);
            TypeReference  parentTypeReference  = visitor.Method.DeclaringType;

            if (parentTypeReference.GenericParameters.Count > 0)
            {
                GenericInstanceType git = new GenericInstanceType(visitor.Method.DeclaringType);

                foreach (GenericParameter gp in originalCall.DeclaringType.GenericParameters)
                {
                    git.GenericArguments.Add(gp);
                }

                parentTypeReference = git;
            }

            // Get the called method
            if (filterAction.Target.Equals(FilterAction.InnerTarget) ||
                filterAction.Target.Equals(FilterAction.SelfTarget))
            {
                if (filterAction.Selector.Equals(originalCall.Name))
                {
                    if (parentTypeReference is GenericInstanceType)
                    {
                        methodReference = new MethodReference(originalCall.Name,
                                                              parentTypeReference, originalCall.ReturnType.ReturnType,
                                                              originalCall.HasThis, originalCall.ExplicitThis,
                                                              originalCall.CallingConvention);
                        methodReference.DeclaringType = parentTypeReference;

                        foreach (ParameterDefinition param in originalCall.Parameters)
                        {
                            methodReference.Parameters.Add(param);
                        }

                        methodReference = visitor.TargetAssemblyDefinition.MainModule.Import(methodReference, parentTypeDefinition);

                        /* This piece of code must solve the following problem:
                         *
                         * class<T> Test
                         * {
                         *    void Func(T a)
                         *    {
                         *       // inner call
                         *       Test<T>.Func(a);
                         *    }
                         * }
                         *
                         * Resolving Test<T> to a GenericInstanceType is no problem
                         * The methodReference must use the GenericInstanceType as its base type
                         * Import the new methodReference before use.
                         */
                    }
                    else
                    {
                        methodReference = originalCall;
                    }
                }
                else
                {
                    methodReference = CecilUtilities.ResolveMethod(parentTypeDefinition,
                                                                   filterAction.Selector, originalCall);
                }
            }
            else
            {
                target = parentTypeDefinition.Fields.GetField(filterAction.Target);
                if (target == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              Properties.Resources.FieldNotFound, filterAction.Target));
                }

                TypeDefinition   fieldType = CecilUtilities.ResolveTypeDefinition(target.FieldType);
                MethodDefinition md        = CecilUtilities.ResolveMethod(fieldType,
                                                                          filterAction.Selector, originalCall);

                if (md == null)
                {
                    throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                              "Method {0} not found in {1}", filterAction.Selector, fieldType.FullName));
                }

                methodReference = visitor.TargetAssemblyDefinition.MainModule.Import(md);
            }

            // If there is no method reference, then we cannot dispatch. Raise an exception.
            if (methodReference == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture,
                                                          Properties.Resources.MethodNotFound, parentTypeReference.ToString(), filterAction.Selector));
            }


            // Check if it is an innercall and set innercall context:
            if (filterAction.Target.Equals(FilterAction.InnerTarget))
            {
                WeaveStrategyUtilities.SetInnerCall(visitor, methodReference);
            }


            // Generic arguments; add the generic parameters as generic argument to a GenericInstanceMethod
            if (originalCall.GenericParameters.Count > 0)
            {
                // Original call has generics, so add to the new memberreference
                GenericInstanceMethod gim = new GenericInstanceMethod(methodReference);
                foreach (GenericParameter gp in originalCall.GenericParameters)
                {
                    gim.GenericArguments.Add(gp);
                }
                methodReference = gim;
            }

            // Place the arguments on the stack first

            // Place target on the stack
            if (methodReference.HasThis)
            {
                if (filterAction.Target.Equals(FilterAction.InnerTarget) ||
                    filterAction.Target.Equals(FilterAction.SelfTarget))
                {
                    WeaveStrategyUtilities.LoadSelfObject(visitor, jpcVar);
                }
                else
                {
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldarg, visitor.Method.This));
                    visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldfld, target));
                }
            }

            // Place arguments on the stack
            WeaveStrategyUtilities.LoadArguments(visitor, originalCall, jpcVar);

            // Call the method
            if (filterAction.Target.Equals(FilterAction.InnerTarget) &&
                filterAction.Selector.Equals(originalCall.Name))
            {
                // Because it is an inner call targeting the method itself, we must call the method
                // in the class itself. Therefore we do a Call instead of a Callvirt, to prevent that
                // the call is dispatched to an overriding method in a subclass.
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, methodReference));
            }
            else if (visitor.CalledMethod.HasThis)
            {
                // Because we dispatch to another method than the original called method, we do a Callvirt
                // so that an overriding method in a subclass may be called.
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, methodReference));
            }
            else
            {
                // static method cannot be called with Callvirt.
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Call, methodReference));
            }

            // Store the return value:
            WeaveStrategyUtilities.StoreReturnValue(visitor, originalCall, jpcVar);

            // Restore arguments:
            WeaveStrategyUtilities.RestoreArguments(visitor, originalCall, jpcVar);
        }
Пример #4
0
        public override void Weave(ICecilInliningInstructionVisitor visitor, FilterAction filterAction,
                                   MethodDefinition originalCall)
        {
            // The method we have to call, an Execute(JoinPointContext) function.
            MethodReference methodToCall;

            // Create FilterAction object:
            FilterActionElement filterActionElement;

            filterActionElement = DefaultWeaveStrategy.GetFilterActionElement(visitor.WeaveConfiguration.FilterActions, filterAction.FullName);

            if (filterActionElement == null)
            {
                throw new ILWeaverException(string.Format(CultureInfo.CurrentCulture, Properties.Resources.CouldNotResolveFilterAction, filterAction.FullName));
            }

            // Get JoinPointContext
            VariableDefinition jpcVar = null;

            if (filterActionElement.CreateJPC)
            {
                jpcVar = visitor.CreateJoinPointContextLocal();
            }

            // Get the methodReference
            MethodReference methodReference = (MethodReference)originalCall;

            // TypeDefinition parentType = CecilUtilities.ResolveTypeDefinition(methodReference.DeclaringType);

            // Set JoinPointContext
            if (filterActionElement.CreateJPC)
            {
                WeaveStrategyUtilities.SetJoinPointContext(visitor, methodReference, filterAction);
            }

            TypeReference typeRef =
                CecilUtilities.ResolveType(filterAction.FullName, filterActionElement.Assembly, null);
            TypeDefinition typeDef =
                CecilUtilities.ResolveTypeDefinition(typeRef);
            MethodReference constructor = typeDef.Constructors.GetConstructor(false, new Type[0]);

            if (constructor == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.TypeNotFound, filterAction.FullName));
            }

            constructor = visitor.TargetAssemblyDefinition.MainModule.Import(constructor);
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Newobj, constructor));

            // Get method to call
            methodToCall = CecilUtilities.ResolveMethod(typeDef, "Execute", new Type[] { typeof(JoinPointContext) });

            // Check for null value
            if (methodToCall == null)
            {
                throw new ILWeaverException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.AdviceMethodNotFound, "Execute", filterAction.FullName));
            }

            methodToCall = visitor.TargetAssemblyDefinition.MainModule.Import(methodToCall);

            // Load the JoinPointObject as the parameter if required
            if (filterActionElement.CreateJPC)
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldloc, jpcVar));
            }
            else
            {
                visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Ldnull));
            }

            // Do the call
            // We can safely emit a callvirt here. The JITter will make the right call.
            visitor.Instructions.Add(visitor.Worker.Create(OpCodes.Callvirt, methodToCall));
        }