예제 #1
0
        /// <summary>   Writes a line. </summary>
        ///
        /// <remarks>   Ken, 10/3/2020. </remarks>
        ///
        /// <param name="format">       Describes the format to use. </param>
        /// <param name="printMode">    The print mode. </param>
        /// <param name="args">         A variable-length parameters list containing arguments. </param>

        public void WriteLine(string format, PrintMode printMode, params object[] args)
        {
            var output = string.Format(format, args);

            if (output.Trim().Length > 0)
            {
                if ((generatorOptions.PrintMode == PrintMode.All && (!printMode.HasFlag(PrintMode.ExcludeFromAll))) || printMode.HasAnyFlag(generatorOptions.PrintMode) || printMode == PrintMode.Any)
                {
                    if (generatorMode == GeneratorMode.Console)
                    {
                        Console.WriteLine(output);
                    }
                    else if (generatorMode == GeneratorMode.RedirectedConsole)
                    {
                        generatorOptions.OutputWriter.WriteLine(output);
                        generatorOptions.OutputWriter.Flush();
                    }
                }
            }
        }
예제 #2
0
        public DynamicMethod ComposePatchedMethod()
        {
            DynamicMethod method    = AllocatePatchMethod();
            var           generator = new LoggingIlGenerator(method.GetILGenerator(),
                                                             PrintMode.HasFlag(PrintModeEnum.EmittedReflection) ? LogLevel.Info : LogLevel.Trace);
            List <MsilInstruction> il = EmitPatched((type, pinned) => new MsilLocal(generator.DeclareLocal(type, pinned))).ToList();

            var dumpTarget = DumpTarget != null?File.CreateText(DumpTarget) : null;

            try
            {
                const string gap = "\n\n\n\n\n";

                void LogTarget(PrintModeEnum mode, bool err, string msg)
                {
                    if (DumpMode.HasFlag(mode))
                    {
                        dumpTarget?.WriteLine((err ? "ERROR " : "") + msg);
                    }
                    if (!PrintMode.HasFlag(mode))
                    {
                        return;
                    }
                    if (err)
                    {
                        _log.Error(msg);
                    }
                    else
                    {
                        _log.Info(msg);
                    }
                }

                if (PrintMsil || DumpTarget != null)
                {
                    lock (_log)
                    {
                        var ctx = new MethodContext(_method);
                        ctx.Read();
                        LogTarget(PrintModeEnum.Original, false, "========== Original method ==========");
                        MethodTranspiler.IntegrityAnalysis((a, b) => LogTarget(PrintModeEnum.Original, a, b), ctx.Instructions, true);
                        LogTarget(PrintModeEnum.Original, false, gap);

                        LogTarget(PrintModeEnum.Emitted, false, "========== Desired method ==========");
                        MethodTranspiler.IntegrityAnalysis((a, b) => LogTarget(PrintModeEnum.Emitted, a, b), il);
                        LogTarget(PrintModeEnum.Emitted, false, gap);
                    }
                }

                MethodTranspiler.EmitMethod(il, generator);

                try
                {
                    PatchUtilities.Compile(method);
                }
                catch
                {
                    lock (_log)
                    {
                        var ctx = new MethodContext(method);
                        ctx.Read();
                        MethodTranspiler.IntegrityAnalysis((err, msg) => _log.Warn(msg), ctx.Instructions);
                    }

                    throw;
                }

                if (PrintMsil || DumpTarget != null)
                {
                    lock (_log)
                    {
                        var ctx = new MethodContext(method);
                        ctx.Read();
                        LogTarget(PrintModeEnum.Patched, false, "========== Patched method ==========");
                        MethodTranspiler.IntegrityAnalysis((a, b) => LogTarget(PrintModeEnum.Patched, a, b), ctx.Instructions, true);
                        LogTarget(PrintModeEnum.Patched, false, gap);
                    }
                }
            }
            finally
            {
                dumpTarget?.Close();
            }

            return(method);
        }