예제 #1
0
        /// <summary>
        /// Weaves method with weaving advices <see cref="IWeavingAdvice"/>.
        /// </summary>
        /// <param name="markedMethod">The marked method.</param>
        /// <param name="context">The context.</param>
        private void RunWeavingAdvices(MarkedNode markedMethod, WeavingContext context)
        {
            var method     = markedMethod.Node.Method;
            var methodName = method.Name;

            // our special recipe, with weaving advices
            var weavingAdvicesMarkers      = GetAllMarkers(markedMethod.Node, context.WeavingAdviceInterfaceType, context).Select(t => t.Item2).ToArray();
            var typeDefinition             = markedMethod.Node.Method.DeclaringType;
            var initialType                = TypeLoader.GetType(typeDefinition);
            var weaverMethodWeavingContext = new WeaverMethodWeavingContext(typeDefinition, initialType, methodName, context, TypeResolver, Logging);

            foreach (var weavingAdviceMarker in weavingAdvicesMarkers)
            {
                Logging.WriteDebug("Weaving method '{0}' using weaving advice '{1}'", method.FullName, weavingAdviceMarker.Type.FullName);
                var weavingAdviceType = TypeLoader.GetType(weavingAdviceMarker.Type);
                var weavingAdvice     = (IWeavingAdvice)Activator.CreateInstance(weavingAdviceType);
                if (weavingAdvice is IMethodWeavingAdvice methodWeavingAdvice && !method.IsGetter && !method.IsSetter)
                {
                    methodWeavingAdvice.Advise(weaverMethodWeavingContext);
                }
            }
            if (weaverMethodWeavingContext.TargetMethodName != methodName)
            {
                method.Name = weaverMethodWeavingContext.TargetMethodName;
            }
        }
예제 #2
0
        /// <summary>
        /// Weaves the specified method.
        /// </summary>
        /// <param name="markedMethod">The marked method.</param>
        /// <param name="types">The types.</param>
        private void WeaveAdvices(MarkedNode markedMethod, Types types)
        {
            var method = markedMethod.Node.Method;

            // sanity check
            var moduleDefinition = method.Module;

            if (method.ReturnType.SafeEquivalent(moduleDefinition.SafeImport(typeof(void))))
            {
                var customAttributes = method.CustomAttributes;
                if (customAttributes.Any(c => c.AttributeType.Name == "AsyncStateMachineAttribute"))
                {
                    Logger.WriteWarning("Advising async void method '{0}' could confuse async advices. Consider switching its return type to async Task.", method.FullName);
                }
            }

            if (method.IsAbstract)
            {
                method.Attributes = (method.Attributes & ~MethodAttributes.Abstract) | MethodAttributes.Virtual;
                Logger.WriteDebug("Weaving abstract method '{0}'", method.FullName);
                WritePointcutBody(method, null, false);
            }
            else if (markedMethod.AbstractTarget)
            {
                Logger.WriteDebug("Weaving and abstracting method '{0}'", method.FullName);
                WritePointcutBody(method, null, true);
            }
            else
            {
                Logger.WriteDebug("Weaving method '{0}'", method.FullName);

                var methodName = method.Name;

                // our special recipe, with weaving advices
                var weavingAdvicesMarkers = GetAllMarkers(markedMethod.Node, types.WeavingAdviceAttributeType, types).ToArray();
                if (weavingAdvicesMarkers.Any())
                {
                    var typeDefinition             = markedMethod.Node.Method.DeclaringType;
                    var initialType                = TypeLoader.GetType(typeDefinition);
                    var weaverMethodWeavingContext = new WeaverMethodWeavingContext(typeDefinition, initialType, methodName, types);
                    foreach (var weavingAdviceMarker in weavingAdvicesMarkers)
                    {
                        var weavingAdviceType   = TypeLoader.GetType(weavingAdviceMarker.Type);
                        var weavingAdvice       = (IWeavingAdvice)Activator.CreateInstance(weavingAdviceType);
                        var methodWeavingAdvice = weavingAdvice as IMethodWeavingAdvice;
                        if (methodWeavingAdvice != null && !method.IsGetter && !method.IsSetter)
                        {
                            methodWeavingAdvice.Advise(weaverMethodWeavingContext);
                        }
                    }
                    if (weaverMethodWeavingContext.TargetMethodName != methodName)
                    {
                        methodName = method.Name = weaverMethodWeavingContext.TargetMethodName;
                    }
                }

                // create inner method
                const MethodAttributes attributesToKeep = MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.PInvokeImpl |
                                                          MethodAttributes.UnmanagedExport | MethodAttributes.HasSecurity |
                                                          MethodAttributes.RequireSecObject;
                var innerMethodAttributes = method.Attributes & attributesToKeep |
                                            (InjectAsPrivate ? MethodAttributes.Private : MethodAttributes.Public);
                string innerMethodName;
                if (method.IsGetter)
                {
                    innerMethodName = GetPropertyInnerGetterName(GetPropertyName(methodName));
                }
                else if (method.IsSetter)
                {
                    innerMethodName = GetPropertyInnerSetterName(GetPropertyName(methodName));
                }
                else
                {
                    innerMethodName = GetInnerMethodName(methodName);
                }
                var innerMethod = new MethodDefinition(innerMethodName, innerMethodAttributes, method.ReturnType);
                innerMethod.GenericParameters.AddRange(method.GenericParameters.Select(p => p.Clone(innerMethod)));
                innerMethod.ImplAttributes      = method.ImplAttributes;
                innerMethod.SemanticsAttributes = method.SemanticsAttributes;
                innerMethod.Parameters.AddRange(method.Parameters);
                if (method.IsPInvokeImpl)
                {
                    innerMethod.PInvokeInfo = method.PInvokeInfo;
                    // must be removed before attributes are updated (otherwise Cecil gets angry)
                    method.PInvokeInfo   = null;
                    method.IsPreserveSig = false;
                    method.IsPInvokeImpl = false;
                }
                else
                {
                    innerMethod.Body.InitLocals = method.Body.InitLocals;
                    innerMethod.Body.Instructions.AddRange(method.Body.Instructions);
                    innerMethod.Body.Variables.AddRange(method.Body.Variables);
                    innerMethod.Body.ExceptionHandlers.AddRange(method.Body.ExceptionHandlers);
                }

                WritePointcutBody(method, innerMethod, false);
                lock (method.DeclaringType)
                    method.DeclaringType.Methods.Add(innerMethod);
            }
        }