// dnlib: See LICENSE.txt for more info using System; using System.Reflection; using dnlib.DotNet.Writer; namespace dnlib.DotNet { /// /// events /// public enum LoggerEvent { /// /// An error was detected. An exception should normally be thrown but the error /// can be ignored. /// Error, /// /// Just a warning and can be ignored. /// Warning, /// /// A normal message /// Info, /// /// A verbose message /// Verbose, /// /// A very verbose message /// VeryVerbose, } /// /// Simple logger /// public interface ILogger { /// /// Log something /// /// Caller or null /// Logger event /// Format /// Arguments void Log(object sender, LoggerEvent loggerEvent, string format, params object[] args); /// /// true if this event is ignored. If the event is ignored, the caller can /// choose not to call . This is useful if it can take time to /// prepare the message. /// /// The logger event bool IgnoresEvent(LoggerEvent loggerEvent); } public static partial class Extensions { /// /// Log an error message /// /// this /// Sender or null /// Message public static void Error(this ILogger logger, object sender, string message) => logger.Log(sender, LoggerEvent.Error, "{0}", message); /// /// Log an error message /// /// this /// Sender or null /// Message /// Message arg #1 public static void Error(this ILogger logger, object sender, string message, object arg1) => logger.Log(sender, LoggerEvent.Error, message, arg1); /// /// Log an error message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 public static void Error(this ILogger logger, object sender, string message, object arg1, object arg2) => logger.Log(sender, LoggerEvent.Error, message, arg1, arg2); /// /// Log an error message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 public static void Error(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) => logger.Log(sender, LoggerEvent.Error, message, arg1, arg2, arg3); /// /// Log an error message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 /// Message arg #4 public static void Error(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) => logger.Log(sender, LoggerEvent.Error, message, arg1, arg2, arg3, arg4); /// /// Log an error message /// /// this /// Sender or null /// Message /// Message arguments public static void Error(this ILogger logger, object sender, string message, params object[] args) => logger.Log(sender, LoggerEvent.Error, message, args); /// /// Log a warning message /// /// this /// Sender or null /// Message public static void Warning(this ILogger logger, object sender, string message) => logger.Log(sender, LoggerEvent.Warning, "{0}", message); /// /// Log a warning message /// /// this /// Sender or null /// Message /// Message arg #1 public static void Warning(this ILogger logger, object sender, string message, object arg1) => logger.Log(sender, LoggerEvent.Warning, message, arg1); /// /// Log a warning message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 public static void Warning(this ILogger logger, object sender, string message, object arg1, object arg2) => logger.Log(sender, LoggerEvent.Warning, message, arg1, arg2); /// /// Log a warning message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 public static void Warning(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) => logger.Log(sender, LoggerEvent.Warning, message, arg1, arg2, arg3); /// /// Log a warning message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 /// Message arg #4 public static void Warning(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) => logger.Log(sender, LoggerEvent.Warning, message, arg1, arg2, arg3, arg4); /// /// Log a warning message /// /// this /// Sender or null /// Message /// Message arguments public static void Warning(this ILogger logger, object sender, string message, params object[] args) => logger.Log(sender, LoggerEvent.Warning, message, args); /// /// Log an info message /// /// this /// Sender or null /// Message public static void Info(this ILogger logger, object sender, string message) => logger.Log(sender, LoggerEvent.Info, "{0}", message); /// /// Log an info message /// /// this /// Sender or null /// Message /// Message arg #1 public static void Info(this ILogger logger, object sender, string message, object arg1) => logger.Log(sender, LoggerEvent.Info, message, arg1); /// /// Log an info message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 public static void Info(this ILogger logger, object sender, string message, object arg1, object arg2) => logger.Log(sender, LoggerEvent.Info, message, arg1, arg2); /// /// Log an info message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 public static void Info(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) => logger.Log(sender, LoggerEvent.Info, message, arg1, arg2, arg3); /// /// Log an info message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 /// Message arg #4 public static void Info(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) => logger.Log(sender, LoggerEvent.Info, message, arg1, arg2, arg3, arg4); /// /// Log an info message /// /// this /// Sender or null /// Message /// Message arguments public static void Info(this ILogger logger, object sender, string message, params object[] args) => logger.Log(sender, LoggerEvent.Info, message, args); /// /// Log a verbose message /// /// this /// Sender or null /// Message public static void Verbose(this ILogger logger, object sender, string message) => logger.Log(sender, LoggerEvent.Verbose, "{0}", message); /// /// Log a verbose message /// /// this /// Sender or null /// Message /// Message arg #1 public static void Verbose(this ILogger logger, object sender, string message, object arg1) => logger.Log(sender, LoggerEvent.Verbose, message, arg1); /// /// Log a verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 public static void Verbose(this ILogger logger, object sender, string message, object arg1, object arg2) => logger.Log(sender, LoggerEvent.Verbose, message, arg1, arg2); /// /// Log a verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 public static void Verbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) => logger.Log(sender, LoggerEvent.Verbose, message, arg1, arg2, arg3); /// /// Log a verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 /// Message arg #4 public static void Verbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) => logger.Log(sender, LoggerEvent.Verbose, message, arg1, arg2, arg3, arg4); /// /// Log a verbose message /// /// this /// Sender or null /// Message /// Message arguments public static void Verbose(this ILogger logger, object sender, string message, params object[] args) => logger.Log(sender, LoggerEvent.Verbose, message, args); /// /// Log a very verbose message /// /// this /// Sender or null /// Message public static void VeryVerbose(this ILogger logger, object sender, string message) => logger.Log(sender, LoggerEvent.VeryVerbose, "{0}", message); /// /// Log a very verbose message /// /// this /// Sender or null /// Message /// Message arg #1 public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1) => logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1); /// /// Log a very verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1, object arg2) => logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1, arg2); /// /// Log a very verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3) => logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1, arg2, arg3); /// /// Log a very verbose message /// /// this /// Sender or null /// Message /// Message arg #1 /// Message arg #2 /// Message arg #3 /// Message arg #4 public static void VeryVerbose(this ILogger logger, object sender, string message, object arg1, object arg2, object arg3, object arg4) => logger.Log(sender, LoggerEvent.VeryVerbose, message, arg1, arg2, arg3, arg4); /// /// Log a very verbose message /// /// this /// Sender or null /// Message /// Message arguments public static void VeryVerbose(this ILogger logger, object sender, string message, params object[] args) => logger.Log(sender, LoggerEvent.VeryVerbose, message, args); } /// /// Dummy logger which ignores all messages, but can optionally throw on errors. /// public sealed class DummyLogger : ILogger { ConstructorInfo ctor; /// /// It ignores everything and doesn't throw anything. /// public static readonly DummyLogger NoThrowInstance = new DummyLogger(); /// /// Throws a on errors, but ignores anything else. /// public static readonly DummyLogger ThrowModuleWriterExceptionOnErrorInstance = new DummyLogger(typeof(ModuleWriterException)); DummyLogger() { } /// /// Constructor /// /// If non-null, this exception type is thrown on /// errors. It must have a public constructor that takes a as the only /// argument. public DummyLogger(Type exceptionToThrow) { if (exceptionToThrow is not null) { if (!exceptionToThrow.IsSubclassOf(typeof(Exception))) throw new ArgumentException($"Not a System.Exception sub class: {exceptionToThrow.GetType()}"); ctor = exceptionToThrow.GetConstructor(new Type[] { typeof(string) }); if (ctor is null) throw new ArgumentException($"Exception type {exceptionToThrow.GetType()} doesn't have a public constructor that takes a string as the only argument"); } } /// public void Log(object sender, LoggerEvent loggerEvent, string format, params object[] args) { if (loggerEvent == LoggerEvent.Error && ctor is not null) throw (Exception)ctor.Invoke(new object[] { string.Format(format, args) }); } /// public bool IgnoresEvent(LoggerEvent loggerEvent) { if (ctor is null) return true; return loggerEvent != LoggerEvent.Error; } } }