Ejemplo n.º 1
0
        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);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        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);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <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());
        }