private void WeaveMethods( TypeDefinition clazz, IReadOnlyList <CrossCutterN.Aspect.Metadata.ICustomAttribute> classCustomAttributes, MethodWeaver methodWeaver, IClassWeavingStatisticsBuilder statistics) { foreach (var method in clazz.Methods) { // methods without bodies can't be injected // property getter and setter will be handled in property phase if (!method.HasBody || IsPropertyMethod(method)) { continue; } var methodInfo = method.Convert(classCustomAttributes); var plan = planner.MakePlan(methodInfo); if (!plan.IsEmpty()) { var methodStatistics = StatisticsFactory.InitializeMethodWeavingRecord(method.Name, method.FullName); methodWeaver.Weave(method, plan, null, methodStatistics); var methodStatisticsFinished = methodStatistics.Build(); if (methodStatisticsFinished != null) { statistics.AddMethodWeavingStatistics(methodStatisticsFinished); } } } }
private void WeaveProperties( TypeDefinition clazz, IReadOnlyList <CrossCutterN.Aspect.Metadata.ICustomAttribute> classCustomAttributes, MethodWeaver methodWeaver, IClassWeavingStatisticsBuilder statistics) { foreach (var property in clazz.Properties) { var propertyInfo = property.Convert(classCustomAttributes); var plan = planner.MakePlan(propertyInfo); if (!plan.IsEmpty()) { var propertyStatistics = StatisticsFactory.InitializePropertyWeavingRecord(property.Name, property.FullName); var getterPlan = plan.GetterPlan; var getter = property.GetMethod; if (!getterPlan.IsEmpty() && getter != null) { methodWeaver.Weave(getter, getterPlan, property.Name, propertyStatistics.GetterContainer); } var setterPlan = plan.SetterPlan; var setter = property.SetMethod; if (!setterPlan.IsEmpty() && setter != null) { methodWeaver.Weave(setter, setterPlan, property.Name, propertyStatistics.SetterContainer); } var propertyStatisticsFinished = propertyStatistics.Build(); if (propertyStatisticsFinished != null) { statistics.AddPropertyWeavingStatistics(propertyStatisticsFinished); } } } }
/// <inheritdoc/> public IAssemblyWeavingStatistics Weave(string inputAssemblyPath, bool includeSymbol, string outputAssemblyPath, string strongNameKeyFile) { if (string.IsNullOrWhiteSpace(inputAssemblyPath)) { throw new ArgumentNullException("inputAssemblyPath"); } if (string.IsNullOrWhiteSpace(outputAssemblyPath)) { throw new ArgumentNullException("outputAssemblyPath"); } // Mono.Cecil implementation has issues that if we directly pass file name for input assembly, // the assembly can't be overwritten if we give the same file name for output assembly, // So here we directly convert input assembly file to memory stream to ensure that input assembly file handle is release when outputing. var readerParameters = new ReaderParameters(); if (includeSymbol) { readerParameters.ReadSymbols = true; readerParameters.SymbolReaderProvider = new PdbReaderProvider(); readerParameters.SymbolStream = new MemoryStream(File.ReadAllBytes(Path.ChangeExtension(inputAssemblyPath, "pdb"))); } var assembly = AssemblyDefinition.ReadAssembly(new MemoryStream(File.ReadAllBytes(inputAssemblyPath)), readerParameters); var assemblyStatistics = StatisticsFactory.InitializeAssemblyWeavingRecord(assembly.FullName); try { foreach (var module in assembly.Modules) { var moduleStatistics = StatisticsFactory.InitializeModuleWeavingRecord(module.Name); var context = WeaverFactory.InitializeMethodWeavingContext(module); foreach (var clazz in module.GetTypes().Where(tp => tp.IsClass && (tp.HasMethods || tp.HasFields))) { // supporting data structure initialization. var classStatistics = StatisticsFactory.InitializeClassWeavingRecord(clazz.Name, clazz.FullName, clazz.Namespace); var switchHandlerBuilder = SwitchFactory.InitializeSwitchHandler(clazz, context.GetTypeReference(typeof(int))); var classCustomAttributes = GetClassCustomAttributes(clazz); var methodWeaver = new MethodWeaver(classCustomAttributes, context, switchHandlerBuilder); WeaveProperties(clazz, classCustomAttributes, methodWeaver, classStatistics); WeaveMethods(clazz, classCustomAttributes, methodWeaver, classStatistics); WeaveSwitches(switchHandlerBuilder.Build(), clazz, context, classStatistics); // handle statistics var classStatisticsFinished = classStatistics.Build(); if (classStatisticsFinished.WeavedMethodPropertyCount > 0) { moduleStatistics.AddClassWeavingStatistics(classStatisticsFinished); } } AddAssemblyReference(context, module, moduleStatistics); // handle statistics. var moduleStatisticsFinished = moduleStatistics.Build(); if (moduleStatisticsFinished.WeavedClassCount > 0) { assemblyStatistics.AddModuleWeavingStatistics(moduleStatisticsFinished); } } var writerParameters = new WriterParameters(); if (includeSymbol) { writerParameters.WriteSymbols = true; writerParameters.SymbolWriterProvider = new PdbWriterProvider(); } if (!string.IsNullOrWhiteSpace(strongNameKeyFile)) { writerParameters.StrongNameKeyPair = new StrongNameKeyPair(File.ReadAllBytes(strongNameKeyFile)); } assembly.Write(outputAssemblyPath, writerParameters); } catch (Exception e) { assemblyStatistics.Exception = e; } return(assemblyStatistics.Build()); }