diff --git a/EonaCat.Logger/EonaCat.Logger.csproj b/EonaCat.Logger/EonaCat.Logger.csproj
index 3f2d3b3..b06968c 100644
--- a/EonaCat.Logger/EonaCat.Logger.csproj
+++ b/EonaCat.Logger/EonaCat.Logger.csproj
@@ -2,9 +2,9 @@
.netstandard2.1; net8.0; net4.8;
icon.ico
- 1.4.8
+ 1.4.9
latest
- 1.4.8
+ 1.4.9
EonaCat (Jeroen Saey)
true
EonaCat (Jeroen Saey)
@@ -25,7 +25,7 @@
- 1.4.8+{chash:10}.{c:ymd}
+ 1.4.9+{chash:10}.{c:ymd}
true
true
v[0-9]*
diff --git a/EonaCat.Logger/Extensions/DateTimeExtensions.cs b/EonaCat.Logger/Extensions/DateTimeExtensions.cs
index 0ffb519..4907149 100644
--- a/EonaCat.Logger/Extensions/DateTimeExtensions.cs
+++ b/EonaCat.Logger/Extensions/DateTimeExtensions.cs
@@ -2,6 +2,9 @@
namespace EonaCat.Logger.Extensions;
+// This file is part of the EonaCat project(s) which is released under the Apache License.
+// See the LICENSE file or go to https://EonaCat.com/License for full license details.
+
public static class DateTimeExtensions
{
public static long ToUnixTimestamp(this DateTime dateTime)
diff --git a/EonaCat.Logger/Extensions/ExceptionExtensions.cs b/EonaCat.Logger/Extensions/ExceptionExtensions.cs
index 4169a3c..cc27a79 100644
--- a/EonaCat.Logger/Extensions/ExceptionExtensions.cs
+++ b/EonaCat.Logger/Extensions/ExceptionExtensions.cs
@@ -1,98 +1,101 @@
-using System;
-using System.Collections;
-using System.Diagnostics;
-using System.Text;
-
-namespace EonaCat.Logger.Extensions;
-
-public static class ExceptionExtensions
-{
- public static string FormatExceptionToMessage(this Exception exception, string module = null, string method = null)
- {
- if (exception == null)
- {
- return string.Empty;
- }
-
- var st = new StackTrace(exception, true);
- var frame = st.GetFrame(0);
- int fileLine = -1;
- string filename = "Unknown";
-
- if (frame != null)
- {
- fileLine = frame.GetFileLineNumber();
- filename = frame.GetFileName();
- }
-
- var sb = new StringBuilder();
-
- sb.AppendLine();
- sb.AppendLine($"--- Exception details provided by {DllInfo.ApplicationName} ---");
- if (!string.IsNullOrEmpty(module))
- {
- sb.AppendLine(" Module : " + module);
- }
-
- if (!string.IsNullOrEmpty(method))
- {
- sb.AppendLine(" Method : " + method);
- }
-
- sb.Append(" Type : ").AppendLine(exception.GetType().ToString());
- sb.Append(" Data : ").AppendLine(exception.Data != null && exception.Data.Count > 0
- ? FormatExceptionData(exception.Data)
- : "(none)");
- sb.Append(" Inner : ").AppendLine(exception.InnerException != null
- ? FormatInnerException(exception.InnerException)
- : "(null)");
- sb.Append(" Message : ").AppendLine(exception.Message);
- sb.Append(" Source : ").AppendLine(exception.Source);
- sb.Append(" StackTrace : ").AppendLine(exception.StackTrace);
- sb.Append(" Line : ").AppendLine(fileLine.ToString());
- sb.Append(" File : ").AppendLine(filename);
- sb.Append(" ToString : ").AppendLine(exception.ToString());
- sb.AppendLine("---");
-
- return sb.ToString();
- }
-
- private static string FormatExceptionData(IDictionary data)
- {
- var sb = new StringBuilder();
-
- foreach (DictionaryEntry entry in data)
- {
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.Text;
+
+namespace EonaCat.Logger.Extensions;
+
+// This file is part of the EonaCat project(s) which is released under the Apache License.
+// See the LICENSE file or go to https://EonaCat.com/License for full license details.
+
+public static class ExceptionExtensions
+{
+ public static string FormatExceptionToMessage(this Exception exception, string module = null, string method = null)
+ {
+ if (exception == null)
+ {
+ return string.Empty;
+ }
+
+ var st = new StackTrace(exception, true);
+ var frame = st.GetFrame(0);
+ int fileLine = -1;
+ string filename = "Unknown";
+
+ if (frame != null)
+ {
+ fileLine = frame.GetFileLineNumber();
+ filename = frame.GetFileName();
+ }
+
+ var sb = new StringBuilder();
+
+ sb.AppendLine();
+ sb.AppendLine($"--- Exception details provided by {DllInfo.ApplicationName} ---");
+ if (!string.IsNullOrEmpty(module))
+ {
+ sb.AppendLine(" Module : " + module);
+ }
+
+ if (!string.IsNullOrEmpty(method))
+ {
+ sb.AppendLine(" Method : " + method);
+ }
+
+ sb.Append(" Type : ").AppendLine(exception.GetType().ToString());
+ sb.Append(" Data : ").AppendLine(exception.Data != null && exception.Data.Count > 0
+ ? FormatExceptionData(exception.Data)
+ : "(none)");
+ sb.Append(" Inner : ").AppendLine(exception.InnerException != null
+ ? FormatInnerException(exception.InnerException)
+ : "(null)");
+ sb.Append(" Message : ").AppendLine(exception.Message);
+ sb.Append(" Source : ").AppendLine(exception.Source);
+ sb.Append(" StackTrace : ").AppendLine(exception.StackTrace);
+ sb.Append(" Line : ").AppendLine(fileLine.ToString());
+ sb.Append(" File : ").AppendLine(filename);
+ sb.Append(" ToString : ").AppendLine(exception.ToString());
+ sb.AppendLine("---");
+
+ return sb.ToString();
+ }
+
+ private static string FormatExceptionData(IDictionary data)
+ {
+ var sb = new StringBuilder();
+
+ foreach (DictionaryEntry entry in data)
+ {
if (entry.Key != null)
{
- sb.Append(" | ")
+ sb.Append(" | ")
.Append(entry.Key);
- }
-
+ }
+
if (entry.Value != null)
{
- sb.Append(": ")
+ sb.Append(": ")
.AppendLine(entry.Value.ToString());
- }
- }
-
- return sb.ToString();
- }
-
- private static string FormatInnerException(Exception innerException)
- {
- var sb = new StringBuilder();
-
- sb.AppendLine(innerException.GetType().ToString())
- .AppendLine(" Message : " + innerException.Message)
- .AppendLine(" Source : " + innerException.Source)
- .AppendLine(" StackTrace : " + innerException.StackTrace)
- .AppendLine(" ToString : " + innerException)
- .Append(" Data : ")
- .AppendLine(innerException.Data != null && innerException.Data.Count > 0
- ? FormatExceptionData(innerException.Data)
- : "(none)");
-
- return sb.ToString();
- }
+ }
+ }
+
+ return sb.ToString();
+ }
+
+ private static string FormatInnerException(Exception innerException)
+ {
+ var sb = new StringBuilder();
+
+ sb.AppendLine(innerException.GetType().ToString())
+ .AppendLine(" Message : " + innerException.Message)
+ .AppendLine(" Source : " + innerException.Source)
+ .AppendLine(" StackTrace : " + innerException.StackTrace)
+ .AppendLine(" ToString : " + innerException)
+ .Append(" Data : ")
+ .AppendLine(innerException.Data != null && innerException.Data.Count > 0
+ ? FormatExceptionData(innerException.Data)
+ : "(none)");
+
+ return sb.ToString();
+ }
}
\ No newline at end of file
diff --git a/EonaCat.Logger/Extensions/ObjectExtensions.cs b/EonaCat.Logger/Extensions/ObjectExtensions.cs
new file mode 100644
index 0000000..31f5289
--- /dev/null
+++ b/EonaCat.Logger/Extensions/ObjectExtensions.cs
@@ -0,0 +1,425 @@
+using EonaCat.Json;
+using EonaCat.Json.Serialization;
+using EonaCat.Logger.Managers;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Serialization;
+
+namespace EonaCat.Logger.Extensions
+{
+ // This file is part of the EonaCat project(s) which is released under the Apache License.
+ // See the LICENSE file or go to https://EonaCat.com/License for full license details.
+
+ public enum DumpFormat
+ {
+ Json,
+ Xml,
+ Tree
+ }
+
+ public static class ObjectExtensions
+ {
+ ///
+ /// Dumps any object to a string in JSON, XML, or detailed tree format.
+ ///
+ /// Object to dump
+ /// "json" (default), "xml", or "tree"
+ /// For JSON: include private/internal fields. Ignored for tree format
+ /// Optional max depth for tree dump. Null = no limit
+ /// Optional max items to display in collections. Null = show all
+ /// String representation of the object
+ public static string Dump(this object currentObject, DumpFormat format = DumpFormat.Json, bool detailed = false, int? maxDepth = null, int? maxCollectionItems = null)
+ {
+ if (currentObject == null)
+ {
+ return "null";
+ }
+
+ try
+ {
+ switch (format)
+ {
+ case DumpFormat.Xml:
+ return DumpXml(currentObject);
+ case DumpFormat.Tree:
+ return DumpTree(currentObject, maxDepth, maxCollectionItems);
+ case DumpFormat.Json:
+ default:
+ return DumpJson(currentObject, detailed);
+ }
+ }
+ catch (Exception ex)
+ {
+ return $"Error dumping object: {ex.Message}";
+ }
+ }
+
+ private static string DumpJson(object currentObject, bool isDetailed)
+ {
+ var settings = new JsonSerializerSettings
+ {
+ ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
+ Formatting = Formatting.Indented
+ };
+
+ if (isDetailed)
+ {
+ settings.ContractResolver = new DefaultContractResolver
+ {
+ IgnoreSerializableAttribute = false,
+ IgnoreSerializableInterface = false
+ };
+ }
+
+ return JsonHelper.ToJson(currentObject, settings);
+ }
+
+ private static string DumpXml(object currentObject)
+ {
+ try
+ {
+ var xmlSerializer = new XmlSerializer(currentObject.GetType());
+ using (var stringWriter = new StringWriter())
+ {
+ xmlSerializer.Serialize(stringWriter, currentObject);
+ return stringWriter.ToString();
+ }
+ }
+ catch (Exception ex)
+ {
+ return $"XML serialization failed: {ex.Message}";
+ }
+ }
+
+ private static string DumpTree(object currentObject, int? maxDepth, int? maxCollectionItems)
+ {
+ var stringBuilder = new StringBuilder();
+ var visitedHashSet = new HashSet