/// <summary> /// Weaves the specified module definition. /// </summary> /// <param name="moduleDefinition">The module definition.</param> public bool Weave(ModuleDefMD moduleDefinition) { var auditTimer = new AuditTimer(); try { // sanity check auditTimer.NewZone("Types import"); // context var context = CreateWeavingContext(moduleDefinition); if (context.AdviceInterfaceType == null) { Logging.WriteWarning("IAdvice interface not found here (not referenced means not used), exiting"); return(false); } // runtime check auditTimer.NewZone("Runtime check"); var targetFramework = GetTargetFramework(moduleDefinition); InjectAsPrivate = targetFramework.Silverlight is null && targetFramework.WindowsPhone is null; // weave methods (they can be property-related, too) auditTimer.NewZone("Weavable methods detection"); Func <MarkedNode, bool> isWeavable = n => !IsFromComputerGeneratedType(n) && IsWeavable(n); var weavingAdvicesMethods = GetMarkedMethods(moduleDefinition, context.WeavingAdviceInterfaceType, context).Where(isWeavable).ToArray(); var weavableMethods = GetMarkedMethods(moduleDefinition, context.AdviceInterfaceType, context).Where(isWeavable).ToArray(); auditTimer.NewZone("Abstract targets"); var generatedFieldsToBeRemoved = new List <FieldDef>(); var methodsWithAbstractTarget = weavableMethods.Where(m => m.AbstractTarget).ToArray(); if (methodsWithAbstractTarget.Length > 0) { generatedFieldsToBeRemoved.AddRange(GetRemovableFields(methodsWithAbstractTarget, context)); foreach (var fieldReference in generatedFieldsToBeRemoved) { Logging.WriteDebug("Field {0} to be removed", fieldReference.FullName); } } auditTimer.NewZone("Methods weaving advice"); weavingAdvicesMethods.ForAll(i => RunWeavingAdvices(i, context)); auditTimer.NewZone("Methods weaving"); weavableMethods.ForAll(m => WeaveMethod(moduleDefinition, m, context)); auditTimer.NewZone("Weavable interfaces detection"); var weavableInterfaces = GetAdviceHandledInterfaces(moduleDefinition).Union(GetDynamicHandledInterfaces(moduleDefinition)).ToArray(); auditTimer.NewZone("Interface methods weaving"); weavableInterfaces.ForAll(i => WeaveInterface(moduleDefinition, i, context)); // and then, the info advices auditTimer.NewZone("Info advices weaving"); var infoAdviceInterface = TypeResolver.Resolve(moduleDefinition, typeof(IInfoAdvice)); moduleDefinition.GetTypes().ForAll(t => WeaveInfoAdvices(moduleDefinition, t, infoAdviceInterface, context)); auditTimer.NewZone("Abstract targets cleanup"); foreach (var generatedFieldToBeRemoved in generatedFieldsToBeRemoved) { generatedFieldToBeRemoved.DeclaringType.Fields.Remove(generatedFieldToBeRemoved); } auditTimer.LastZone(); var report = auditTimer.GetReport(); var maxLength = report.Keys.Max(k => k.Length); Logging.WriteDebug("--- Timings --------------------------"); foreach (var reportPart in report) { Logging.WriteDebug("{0} : {1}ms", reportPart.Key.PadRight(maxLength), (int)reportPart.Value.TotalMilliseconds); } Logging.WriteDebug("--------------------------------------"); var thisAssembly = GetType().Assembly; var thisVersion = thisAssembly.GetCustomAttribute <AssemblyVersionAttribute>()?.Version ?? thisAssembly.GetCustomAttribute <AssemblyInformationalVersionAttribute>()?.InformationalVersion; var thisTargetFramework = TargetFramework.FromLiteral(thisAssembly.GetCustomAttribute <TargetFrameworkAttribute>()?.FrameworkName); Logging.Write("MrAdvice {3}/{4} weaved module '{0}' (targeting framework {2}) in {1}ms", moduleDefinition.Assembly.FullName, (int)report.Sum(r => r.Value.TotalMilliseconds), targetFramework.ToString(), thisVersion, thisTargetFramework); return(true); } catch (Exception e) { Logging.WriteError("Internal error during {0}: {1}", auditTimer.CurrentZoneName, e); Logging.WriteError("Please complain, whine, cry, yell at https://github.com/ArxOne/MrAdvice/issues/new"); return(false); } }
/// <summary> /// Weaves the specified module definition. /// </summary> /// <param name="moduleDefinition">The module definition.</param> public void Weave(ModuleDefinition moduleDefinition) { var auditTimer = new AuditTimer(); var stopwatch = new Stopwatch(); stopwatch.Start(); // sanity check auditTimer.NewZone("IAdvice location"); var adviceInterface = TypeResolver.Resolve(moduleDefinition, Binding.AdviceInterfaceName, true); if (adviceInterface == null) { Logger.WriteWarning("IAdvice interface not found here, exiting"); return; } // runtime check auditTimer.NewZone("Runtime check"); var targetFramework = GetTargetFramework(moduleDefinition); InjectAsPrivate = targetFramework.Silverlight == null && targetFramework.WindowsPhone == null; //Logger.WriteDebug("t1: {0}ms", (int)stopwatch.ElapsedMilliseconds); // weave methods (they can be property-related, too) auditTimer.NewZone("Weavable methods detection"); var weavableMethods = GetMarkedMethods(moduleDefinition, adviceInterface).ToArray(); auditTimer.NewZone("Methods weaving"); weavableMethods.AsParallel().ForAll(m => WeaveMethod(moduleDefinition, m, adviceInterface)); auditTimer.NewZone("Weavable interfaces detection"); var weavableInterfaces = GetAdviceHandledInterfaces(moduleDefinition).ToArray(); auditTimer.NewZone("Interface methods weaving"); weavableInterfaces.AsParallel().ForAll(i => WeaveInterface(moduleDefinition, i)); //Logger.WriteDebug("t2: {0}ms", (int)stopwatch.ElapsedMilliseconds); // and then, the info advices auditTimer.NewZone("Info advices weaving"); var infoAdviceInterface = TypeResolver.Resolve(moduleDefinition, Binding.InfoAdviceInterfaceName, true); moduleDefinition.GetTypes().AsParallel().ForAll(t => WeaveInfoAdvices(moduleDefinition, t, infoAdviceInterface)); auditTimer.LastZone(); //Logger.WriteDebug("t3: {0}ms", (int)stopwatch.ElapsedMilliseconds); var report = auditTimer.GetReport(); var maxLength = report.Keys.Max(k => k.Length); Logger.WriteDebug("--- Timings --------------------------"); foreach (var reportPart in report) Logger.WriteDebug("{0} : {1}ms", reportPart.Key.PadRight(maxLength), (int)reportPart.Value.TotalMilliseconds); Logger.WriteDebug("--------------------------------------"); Logger.Write("MrAdvice {3} weaved module '{0}' (targeting framework {2}) in {1}ms", moduleDefinition.Assembly.FullName, (int)stopwatch.ElapsedMilliseconds, targetFramework, Product.Version); }
/// <summary> /// Weaves the specified module definition. /// </summary> /// <param name="moduleDefinition">The module definition.</param> public void Weave(ModuleDefinition moduleDefinition) { var auditTimer = new AuditTimer(); var stopwatch = new Stopwatch(); stopwatch.Start(); // sanity check auditTimer.NewZone("IAdvice location"); var adviceInterface = TypeResolver.Resolve(moduleDefinition, typeof(IAdvice)); if (adviceInterface == null) { Logger.WriteWarning("IAdvice interface not found here (not referenced means not used), exiting"); return; } // context var types = new Types { CompilerGeneratedAttributeType = moduleDefinition.Import(typeof(CompilerGeneratedAttribute)), PriorityAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(PriorityAttribute)), AbstractTargetAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(AbstractTargetAttribute)), WeavingAdviceAttributeType = TypeResolver.Resolve(moduleDefinition, typeof(IWeavingAdvice)) }; // runtime check auditTimer.NewZone("Runtime check"); var targetFramework = GetTargetFramework(moduleDefinition); InjectAsPrivate = targetFramework.Silverlight == null && targetFramework.WindowsPhone == null; //Logger.WriteDebug("t1: {0}ms", (int)stopwatch.ElapsedMilliseconds); // weave methods (they can be property-related, too) auditTimer.NewZone("Weavable methods detection"); var weavableMethods = GetMarkedMethods(moduleDefinition, adviceInterface, types).Where(IsWeavable).ToArray(); auditTimer.NewZone("Abstract targets"); var generatedFieldsToBeRemoved = new List <FieldReference>(); var methodsWithAbstractTarget = weavableMethods.Where(m => m.AbstractTarget).ToArray(); if (methodsWithAbstractTarget.Length > 0) { generatedFieldsToBeRemoved.AddRange(GetRemovableFields(methodsWithAbstractTarget, types)); foreach (var fieldReference in generatedFieldsToBeRemoved) { Logger.WriteDebug("Field {0} to be removed", fieldReference.FullName); } } auditTimer.NewZone("Methods weaving"); weavableMethods.AsParallel().ForAll(m => WeaveMethod(moduleDefinition, m, adviceInterface, types)); auditTimer.NewZone("Weavable interfaces detection"); var weavableInterfaces = GetAdviceHandledInterfaces(moduleDefinition).ToArray(); auditTimer.NewZone("Interface methods weaving"); weavableInterfaces.AsParallel().ForAll(i => WeaveInterface(moduleDefinition, i)); //Logger.WriteDebug("t2: {0}ms", (int)stopwatch.ElapsedMilliseconds); // and then, the info advices auditTimer.NewZone("Info advices weaving"); var infoAdviceInterface = TypeResolver.Resolve(moduleDefinition, typeof(IInfoAdvice)); moduleDefinition.GetTypes() .AsParallel() .ForAll(t => WeaveInfoAdvices(moduleDefinition, t, infoAdviceInterface, types)); auditTimer.NewZone("Abstract targets cleanup"); foreach (var generatedFieldToBeRemoved in generatedFieldsToBeRemoved) { generatedFieldToBeRemoved.DeclaringType.Resolve().Fields.Remove(generatedFieldToBeRemoved.Resolve()); } auditTimer.LastZone(); //Logger.WriteDebug("t3: {0}ms", (int)stopwatch.ElapsedMilliseconds); var report = auditTimer.GetReport(); var maxLength = report.Keys.Max(k => k.Length); Logger.WriteDebug("--- Timings --------------------------"); foreach (var reportPart in report) { Logger.WriteDebug("{0} : {1}ms", reportPart.Key.PadRight(maxLength), (int)reportPart.Value.TotalMilliseconds); } Logger.WriteDebug("--------------------------------------"); Logger.Write("MrAdvice {3} weaved module '{0}' (targeting framework {2}) in {1}ms", moduleDefinition.Assembly.FullName, (int)stopwatch.ElapsedMilliseconds, targetFramework, Product.Version); }