diff --git a/CLI/Program.cs b/CLI/Program.cs index 6e668b8..016ff83 100644 --- a/CLI/Program.cs +++ b/CLI/Program.cs @@ -6,7 +6,6 @@ using Serilog; using ILogger = Serilog.ILogger; var serilogLogger = SetupSerilog(); - LogService.AddLogAdapter(new SerilogAdapter(serilogLogger)); var logger = LogService.RegisterLogger(typeof(Program)); diff --git a/DotBased.Logging.Serilog/SerilogAdapter.cs b/DotBased.Logging.Serilog/SerilogAdapter.cs index 4a41db8..b79a882 100644 --- a/DotBased.Logging.Serilog/SerilogAdapter.cs +++ b/DotBased.Logging.Serilog/SerilogAdapter.cs @@ -38,6 +38,7 @@ public class SerilogAdapter : LogAdapterBase } switch (capsule.Severity) { + case LogSeverity.Verbose: case LogSeverity.Trace: default: logger.Write(new LogEvent(capsule.TimeStamp, LogEventLevel.Verbose, null, template, properties ?? ArraySegment.Empty, ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom())); diff --git a/DotBased/Collections/InstanceContainer.cs b/DotBased/Collections/InstanceContainer.cs new file mode 100644 index 0000000..beb2265 --- /dev/null +++ b/DotBased/Collections/InstanceContainer.cs @@ -0,0 +1,97 @@ +using DotBased.Logging; + +namespace DotBased.Collections; + +/// +/// Container to store instances +/// WIP! +/// +public class InstanceContainer : IDisposable +{ + private readonly ILogger _log = LogService.RegisterLogger(typeof(InstanceContainer)); + private readonly Dictionary _tCollection = new Dictionary(); + + /// + /// Register a instance. + /// + /// The instace will be created by the function + /// Key to indentify the instance + /// The instance type + public void Register(string key) => _tCollection.Add(key, new InstanceNode(null, typeof(TInstance))); + + /// + /// Add an already constructed instance to the container. + /// + /// Key to identify instance + /// Constructed instance + public void Add(string key, object instance) => _tCollection.Add(key, new InstanceNode(instance, instance.GetType())); + + /// + /// Remove a instance from the container. + /// + /// Key to get the instance + /// Dispose the instance if it inherits the 'IDisposable' interface + public void Remove(string key, bool dispose = true) + { + if (!_tCollection.TryGetValue(key, out var iNode)) + return; + switch (iNode.Instance) + { + case null: + break; + case IDisposable instance when dispose: + _log.Debug("Disposing disposable object... (InstanceContainer)"); + instance.Dispose(); + break; + } + _tCollection.Remove(key); + } + + /// + /// Get the instance that is stored in the container. + /// + /// If the instance is not yet constructed this wil activate the instance + /// Key to identify the instance + /// Instasnce type + /// The instance that is at the given key + public TInstance? Get(string key) + { + if (!_tCollection.TryGetValue(key, out InstanceNode node) || node.InstanceType != typeof(TInstance)) + return default; + if (node.Instance != null) + return (TInstance)node.Instance; + node.Instance = Activator.CreateInstance(node.InstanceType); + // Override the old node with the new data, else the next 'Get' will reactivate a another instance. + _tCollection[key] = node; + if (node.Instance != null) return (TInstance)node.Instance; + _log.Warning("Instance is null!"); + return default; + } + + + public void Dispose() + { + foreach (var kvp in _tCollection) + { + switch (kvp.Value.Instance) + { + case null: + continue; + case IDisposable disposable: + _log.Verbose("Disposing: {Key}", kvp.Key); + disposable.Dispose(); + break; + } + } + } +} +internal struct InstanceNode +{ + public InstanceNode(object? instance, Type instanceType) + { + Instance = instance; + InstanceType = instanceType; + } + public object? Instance; + public readonly Type InstanceType; +} \ No newline at end of file diff --git a/DotBased/Collections/KeyContainerBase.cs b/DotBased/Collections/KeyContainerBase.cs new file mode 100644 index 0000000..9332227 --- /dev/null +++ b/DotBased/Collections/KeyContainerBase.cs @@ -0,0 +1,45 @@ +using System.Collections.ObjectModel; + +namespace DotBased.Collections; + +/// +/// Base class for creating containers that has tree like keys +/// +/// The separator used for the keys +/// Container data value +public abstract class KeyContainerBase(char separator = '.') + where TContainer : KeyContainerBase, new() +{ + private readonly Dictionary _containers = new Dictionary(); + public ReadOnlyDictionary Containers => new ReadOnlyDictionary(_containers); + + public TContainer this[string key] + { + get + { + if (key.Contains(separator)) + return AddFromQueue(new KeyQueue(key, separator)); + if (!_containers.ContainsKey(key)) + AddContainer(key, new TContainer()); + return _containers[key]; + } + } + public void AddContainer(string key, TContainer container) => _containers[key] = container; + public bool RemoveContainer(string key) => _containers.Remove(key); + public TContainer GetContainer(string key) => _containers[key]; + + TContainer AddFromQueue(KeyQueue queue) + { + if (queue.IsEmpty) return (TContainer)this; + string queueKey = queue.Next(); + AddContainer(queueKey, new TContainer()); + return _containers[queueKey].AddFromQueue(queue); + } +} +internal class KeyQueue(string key, char divider) +{ + public string Next() => _key.Dequeue(); + public bool IsEmpty => _key.Count <= 0; + + private readonly Queue _key = new Queue(key.Split(divider, StringSplitOptions.RemoveEmptyEntries)); +} \ No newline at end of file diff --git a/DotBased/Collections/PropertyContainer.cs b/DotBased/Collections/PropertyContainer.cs new file mode 100644 index 0000000..c95a7f0 --- /dev/null +++ b/DotBased/Collections/PropertyContainer.cs @@ -0,0 +1,74 @@ +using System.Collections.ObjectModel; + +namespace DotBased.Collections; + +/// +/// Property container to store string, long, int, double and bool properties +/// +public class PropertyContainer : KeyContainerBase +{ + public PropertyContainer() + { } + public PropertyContainer(char separator) : base(separator) + { } + + private readonly Dictionary _data = new Dictionary(); + public ReadOnlyDictionary Data => new ReadOnlyDictionary(_data); + + /// + /// Set a property with the corresponding key. + /// + /// The key that will correspond to the property + /// The string property value + /// If the key already exists overwrite the property + public void Set(string key, string sValue, bool overridable = true) + { + if (ContainsKey(key) && !overridable) + return; + _data[key] = sValue; + } + + public void Set(string key, long lValue, bool overridable = true) + { + if (ContainsKey(key) && !overridable) + return; + _data[key] = lValue; + } + + public void Set(string key, double dValue, bool overridable = true) + { + if (ContainsKey(key) && !overridable) + return; + _data[key] = dValue; + } + + public void Set(string key, bool bValue, bool overridable = true) + { + if (ContainsKey(key) && !overridable) + return; + _data[key] = bValue; + } + + /// + /// Check if the key exists in this container. + /// + /// The key to check + /// True if the key exists otherwise false + public bool ContainsKey(string key) => _data.ContainsKey(key); + + public string GetString(string key) => Convert.ToString(_data[key]) ?? string.Empty; + public long GetLong(string key) => Convert.ToInt64(_data[key]); + public double GetDouble(string key) => Convert.ToDouble(_data[key]); + public bool GetBool(string key) => Convert.ToBoolean(_data[key]); + + /// + /// Removes the property at the passed key. + /// + /// The key where to remove the property + /// True is the property is removed otherwise false + public bool Remove(string key) => _data.Remove(key); + /// + /// Clears all the properties in this container. + /// + public void ClearData() => _data.Clear(); +} \ No newline at end of file diff --git a/DotBased/DotBased.csproj b/DotBased/DotBased.csproj index 070c822..291f62d 100644 --- a/DotBased/DotBased.csproj +++ b/DotBased/DotBased.csproj @@ -7,8 +7,4 @@ default - - - - diff --git a/DotBased/Logging/ILogger.cs b/DotBased/Logging/ILogger.cs index 7732999..2b809f6 100644 --- a/DotBased/Logging/ILogger.cs +++ b/DotBased/Logging/ILogger.cs @@ -5,6 +5,8 @@ namespace DotBased.Logging; /// public interface ILogger { + public void Verbose(string message, params object?[]? parameters); + public void Trace(string message, params object?[]? parameters); public void Debug(string message, params object?[]? parameters); diff --git a/DotBased/Logging/LogSeverity.cs b/DotBased/Logging/LogSeverity.cs index 26bd927..edb2da3 100644 --- a/DotBased/Logging/LogSeverity.cs +++ b/DotBased/Logging/LogSeverity.cs @@ -2,10 +2,11 @@ namespace DotBased.Logging; public enum LogSeverity { - Trace = 0, - Debug = 1, - Info = 2, - Warning = 3, - Error = 4, - Fatal = 5 + Verbose = 0, + Trace = 1, + Debug = 2, + Info = 3, + Warning = 4, + Error = 5, + Fatal = 6 } \ No newline at end of file diff --git a/DotBased/Logging/Logger.cs b/DotBased/Logging/Logger.cs index cc8a293..b5a673a 100644 --- a/DotBased/Logging/Logger.cs +++ b/DotBased/Logging/Logger.cs @@ -10,6 +10,18 @@ public class Logger(CallerInformation caller, ref Action logProcesso ProcessLog(capsule); } + public override void Verbose(string message, params object?[]? parameters) + { + Log(new LogCapsule() + { + Logger = this, + Message = message, + Parameters = parameters, + Severity = LogSeverity.Verbose, + TimeStamp = DateTime.Now + }); + } + public override void Trace(string message, params object?[]? parameters) { Log(new LogCapsule() diff --git a/DotBased/Logging/LoggerBase.cs b/DotBased/Logging/LoggerBase.cs index d9f4652..2c73653 100644 --- a/DotBased/Logging/LoggerBase.cs +++ b/DotBased/Logging/LoggerBase.cs @@ -11,6 +11,7 @@ public abstract class LoggerBase(CallerInformation caller, ref Action ProcessLog = logProcessorHandler; + public abstract void Verbose(string message, params object?[]? parameters); public abstract void Trace(string message, params object?[]? parameters); public abstract void Debug(string message, params object?[]? parameters); public abstract void Information(string message, params object?[]? parameters);