diff --git a/Lib.Logging/Exceptions/LogNotInitializedException.cs b/Lib.Logging/Exceptions/LogNotInitializedException.cs
new file mode 100644
index 0000000..10f5e7a
--- /dev/null
+++ b/Lib.Logging/Exceptions/LogNotInitializedException.cs
@@ -0,0 +1,17 @@
+// Author: Simon Gockner
+// Created: 2020-09-12
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+
+namespace Lib.Logging.Exceptions
+{
+ public class LogNotInitializedException : Exception
+ {
+ public LogNotInitializedException()
+ : base("Log is not initialized yet.")
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Factories/ILogFactory.cs b/Lib.Logging/Factories/ILogFactory.cs
new file mode 100644
index 0000000..4dfe2f3
--- /dev/null
+++ b/Lib.Logging/Factories/ILogFactory.cs
@@ -0,0 +1,9 @@
+using Lib.Logging.Interfaces;
+
+namespace Lib.Logging.Factories
+{
+ public interface ILogFactory
+ {
+ ILog Create();
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Interfaces/ILog.cs b/Lib.Logging/Interfaces/ILog.cs
new file mode 100644
index 0000000..0a454f6
--- /dev/null
+++ b/Lib.Logging/Interfaces/ILog.cs
@@ -0,0 +1,46 @@
+// Author: Gockner, Simon
+// Created: 2019-09-26
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+using System.Threading.Tasks;
+using Lib.Logging.Loggers.Interfaces;
+
+namespace Lib.Logging.Interfaces
+{
+ ///
+ /// The main logging interface
+ ///
+ public interface ILog : IAsyncDisposable
+ {
+ ///
+ /// Initialize the
+ ///
+ /// True if successful, false if not
+ bool InitializeLog();
+
+ ///
+ /// Set the of the current instance
+ ///
+ /// The
+ void SetLogLevel(LogLevels logLevel);
+
+ ///
+ /// Add an to the
+ ///
+ /// The
+ void AddLogger(ILogger logger);
+
+ ///
+ /// Remove an from the
+ ///
+ /// The
+ void RemoveLogger(ILogger logger);
+
+ ///
+ /// Write a header to all loggers
+ ///
+ /// A to wait on
+ Task WriteLogHeader();
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Interfaces/ILogComponent.cs b/Lib.Logging/Interfaces/ILogComponent.cs
new file mode 100644
index 0000000..f7384c5
--- /dev/null
+++ b/Lib.Logging/Interfaces/ILogComponent.cs
@@ -0,0 +1,17 @@
+// Author: Gockner, Simon
+// Created: 2019-09-26
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+namespace Lib.Logging.Interfaces
+{
+ ///
+ /// The
+ ///
+ public interface ILogComponent
+ {
+ ///
+ /// The
+ ///
+ string Component { get; }
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Interfaces/ILogMessage.cs b/Lib.Logging/Interfaces/ILogMessage.cs
new file mode 100644
index 0000000..4d842ca
--- /dev/null
+++ b/Lib.Logging/Interfaces/ILogMessage.cs
@@ -0,0 +1,34 @@
+// Author: Gockner, Simon
+// Created: 2019-09-27
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+
+namespace Lib.Logging.Interfaces
+{
+ ///
+ /// An interface that is used to handle log messages
+ ///
+ public interface ILogMessage
+ {
+ ///
+ /// The of the
+ ///
+ LogLevels LogLevel { get; set; }
+
+ ///
+ /// The of the
+ ///
+ DateTime Timestamp { get; set; }
+
+ ///
+ /// The of the
+ ///
+ ILogComponent? Component { get; set; }
+
+ ///
+ /// The of the
+ ///
+ string? Message { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Interfaces/LogLevels.cs b/Lib.Logging/Interfaces/LogLevels.cs
new file mode 100644
index 0000000..cdd82d0
--- /dev/null
+++ b/Lib.Logging/Interfaces/LogLevels.cs
@@ -0,0 +1,37 @@
+// Author: Gockner, Simon
+// Created: 2019-09-26
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+namespace Lib.Logging.Interfaces
+{
+ ///
+ /// The available
+ ///
+ public enum LogLevels
+ {
+ ///
+ /// No logging
+ ///
+ None,
+
+ ///
+ /// Error logging
+ ///
+ Error,
+
+ ///
+ /// Default logging
+ ///
+ Default,
+
+ ///
+ /// Advanced logging
+ ///
+ Advanced,
+
+ ///
+ /// Debug logging
+ ///
+ Debug
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Lib.Logging.csproj b/Lib.Logging/Lib.Logging.csproj
new file mode 100644
index 0000000..aa23112
--- /dev/null
+++ b/Lib.Logging/Lib.Logging.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net5.0
+ enable
+ 9
+
+
+
+
+
+
+
diff --git a/Lib.Logging/Log.cs b/Lib.Logging/Log.cs
new file mode 100644
index 0000000..0af8e1e
--- /dev/null
+++ b/Lib.Logging/Log.cs
@@ -0,0 +1,218 @@
+// Author: Gockner, Simon
+// Created: 2019-09-26
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Threading.Tasks;
+using Lib.Logging.Exceptions;
+using Lib.Logging.Interfaces;
+using Lib.Logging.Loggers.Interfaces;
+using Lib.Tools;
+
+namespace Lib.Logging
+{
+ ///
+ /// The main logging class
+ ///
+ public class Log : ILog
+ {
+ ///
+ /// Constructor for
+ ///
+ public Log() => Loggers = new List();
+
+ ///
+ /// of s that are subscribed to this
+ ///
+ protected static List? Loggers { get; private set; }
+
+ ///
+ /// The of this logging instance
+ ///
+ protected static LogLevels LogLevel { get; private set; } = LogLevels.Default; //TODO: Move LogLevel to ILogger? Allows to set logLevel separately for each ILogger
+
+ ///
+ /// Initialize the
+ ///
+ /// True if successful, false if not
+ public bool InitializeLog()
+ {
+ return true;
+ }
+
+ ///
+ /// Set the of the current instance
+ ///
+ /// The
+ public void SetLogLevel(LogLevels logLevel)
+ {
+ LogLevel = logLevel;
+ LogLevelChanged?.Invoke(this, LogLevel);
+ }
+
+ ///
+ /// Add an to the
+ ///
+ /// The
+ public void AddLogger(ILogger logger) => Loggers?.Add(logger);
+
+ ///
+ /// Remove an from the
+ ///
+ /// The
+ public void RemoveLogger(ILogger logger) => Loggers?.Remove(logger);
+
+ ///
+ /// Write a given to the set s
+ ///
+ /// The
+ /// The of the caller
+ public static async Task Write(Exception ex)
+ {
+ ILogComponent component = GetDefaultComponentFromType();
+
+ await Write(component, LogLevels.Error, ex.Message);
+ await Write(component, LogLevels.Error, "");
+ await Write(component, LogLevels.Error, ex.StackTrace);
+ }
+
+ ///
+ /// Write a given to the set s
+ ///
+ /// The
+ /// The
+ public static async Task Write(ILogComponent component, Exception ex)
+ {
+ await Write(component, LogLevels.Error, ex.Message);
+ await Write(component, LogLevels.Error, "");
+ await Write(component, LogLevels.Error, ex.StackTrace);
+ }
+
+ ///
+ /// Write a given to the set s
+ ///
+ /// The
+ /// The of the caller
+ public static async Task Write(AggregateException ex)
+ {
+ ILogComponent component = GetDefaultComponentFromType();
+
+ await Write(component, LogLevels.Error, ex.Message);
+ await Write(component, LogLevels.Error, "");
+ await Write(component, LogLevels.Error, ex.StackTrace);
+ await Write(component, LogLevels.Error, "");
+
+ foreach (var innerException in ex.InnerExceptions)
+ {
+ await Write(component, innerException);
+ await Write(component, LogLevels.Error, "");
+ }
+ }
+
+ ///
+ /// Write a given with the to the set s
+ ///
+ ///
+ /// The of the caller
+ public static async Task Write(string line)
+ {
+ ILogComponent component = GetDefaultComponentFromType();
+ await Write(component, LogLevels.Default, line);
+ }
+
+ ///
+ /// Write a given with the of the calling and the to the set s
+ ///
+ /// The
+ /// The given
+ /// The of the caller
+ public static async Task Write(LogLevels logLevel, string line)
+ {
+ ILogComponent component = GetDefaultComponentFromType();
+ await Write(component, logLevel, line);
+ }
+
+ ///
+ /// Write a given with the and the to the set s
+ ///
+ /// The
+ /// The
+ /// The given
+ /// Log is not initialized yet
+ public static async Task Write(ILogComponent component, LogLevels logLevel, string line)
+ {
+ if (logLevel > LogLevel) //logLevel of the message can't be higher than the set LogLevel
+ return;
+
+ ILogMessage message = new LogMessage()
+ {
+ LogLevel = logLevel,
+ Timestamp = DateTime.Now,
+ Component = component,
+ Message = line
+ };
+
+ if (Loggers == null)
+ throw new LogNotInitializedException();
+
+ foreach (var logger in Loggers)
+ {
+ await logger.Write(message);
+ }
+ }
+
+ ///
+ /// Get the default for the given
+ ///
+ /// The
+ ///
+ protected static ILogComponent GetDefaultComponentFromType()
+ {
+ Assembly assembly = Assembly.GetAssembly(typeof(T));
+ LogComponentAttribute attribute = assembly.GetCustomAttribute();
+ return attribute ?? new LogComponentAttribute("UNKNOWN");
+ }
+
+ ///
+ /// Write a header to all loggers
+ ///
+ /// A to wait on
+ public async Task WriteLogHeader()
+ {
+ await Write($"Mystify {Versions.GetVersion()}");
+ await Write($"User: {Environment.UserName}");
+ await Write($"Date: {DateTime.Today:dd.MM.yyyy}");
+ await Write($"OS: {Environment.OSVersion}");
+ await Write($"CLR-Version: {Environment.Version}");
+
+ await Write("");
+ }
+
+ ///
+ /// the
+ ///
+ public async ValueTask DisposeAsync()
+ {
+ if (Loggers != null)
+ {
+ foreach (var logger in Loggers)
+ {
+ await logger.DisposeAsync();
+ }
+
+ Loggers.Clear();
+ }
+
+ LogLevel = LogLevels.None;
+ }
+
+
+ ///
+ /// Event that is fired when is called
+ /// is the newly set
+ ///
+ public static event EventHandler? LogLevelChanged;
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/LogComponentAttribute.cs b/Lib.Logging/LogComponentAttribute.cs
new file mode 100644
index 0000000..0921139
--- /dev/null
+++ b/Lib.Logging/LogComponentAttribute.cs
@@ -0,0 +1,33 @@
+// Author: Gockner, Simon
+// Created: 2019-09-26
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+using Lib.Logging.Interfaces;
+
+namespace Lib.Logging
+{
+ ///
+ /// The attribute
+ ///
+ [AttributeUsage(AttributeTargets.Assembly)]
+ public class LogComponentAttribute : Attribute, ILogComponent
+ {
+ ///
+ /// constructor
+ ///
+ /// The
+ public LogComponentAttribute(string component) => Component = component;
+
+ ///
+ /// The
+ ///
+ public string Component { get; }
+
+ ///
+ /// Returns the of this
+ ///
+ /// The
+ public override string ToString() => Component;
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/LogMessage.cs b/Lib.Logging/LogMessage.cs
new file mode 100644
index 0000000..c681496
--- /dev/null
+++ b/Lib.Logging/LogMessage.cs
@@ -0,0 +1,41 @@
+// Author: Gockner, Simon
+// Created: 2019-09-27
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+using Lib.Logging.Interfaces;
+
+namespace Lib.Logging
+{
+ ///
+ /// Implementation of
+ ///
+ public class LogMessage : ILogMessage
+ {
+ ///
+ /// The of the
+ ///
+ public LogLevels LogLevel { get; set; }
+
+ ///
+ /// The of the
+ ///
+ public DateTime Timestamp { get; set; }
+
+ ///
+ /// The of the
+ ///
+ public ILogComponent? Component { get; set; }
+
+ ///
+ /// The of the
+ ///
+ public string? Message { get; set; }
+
+ ///
+ /// Builds the out of all parts and returns it as a
+ ///
+ /// The as a
+ public override string ToString() => $"{Timestamp:u}: [{Component}] {Message}\n";
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Loggers/ConsoleLogger.cs b/Lib.Logging/Loggers/ConsoleLogger.cs
new file mode 100644
index 0000000..b478cb7
--- /dev/null
+++ b/Lib.Logging/Loggers/ConsoleLogger.cs
@@ -0,0 +1,28 @@
+// Author: Gockner, Simon
+// Created: 2019-09-26
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+using System.Threading.Tasks;
+using Lib.Logging.Interfaces;
+using Lib.Logging.Loggers.Interfaces;
+
+namespace Lib.Logging.Loggers
+{
+ ///
+ /// An that writes log messages to the
+ ///
+ public class ConsoleLogger : IConsoleLogger
+ {
+ ///
+ /// Write the given to the
+ ///
+ /// The
+ public async Task Write(ILogMessage message) => await Task.Run(() => Console.Write(message.ToString()));
+
+ ///
+ /// the
+ ///
+ public async ValueTask DisposeAsync() => await Task.Run(Console.Clear);
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Loggers/Factories/IConsoleLoggerFactory.cs b/Lib.Logging/Loggers/Factories/IConsoleLoggerFactory.cs
new file mode 100644
index 0000000..b551069
--- /dev/null
+++ b/Lib.Logging/Loggers/Factories/IConsoleLoggerFactory.cs
@@ -0,0 +1,13 @@
+// Author: Gockner, Simon
+// Created: 2019-11-24
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using Lib.Logging.Loggers.Interfaces;
+
+namespace Lib.Logging.Loggers.Factories
+{
+ public interface IConsoleLoggerFactory
+ {
+ IConsoleLogger Create();
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Loggers/Factories/IFileLoggerFactory.cs b/Lib.Logging/Loggers/Factories/IFileLoggerFactory.cs
new file mode 100644
index 0000000..b6d9ff7
--- /dev/null
+++ b/Lib.Logging/Loggers/Factories/IFileLoggerFactory.cs
@@ -0,0 +1,13 @@
+// Author: Gockner, Simon
+// Created: 2019-11-24
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using Lib.Logging.Loggers.Interfaces;
+
+namespace Lib.Logging.Loggers.Factories
+{
+ public interface IFileLoggerFactory
+ {
+ IFileLogger Create(string filePath, string fileName);
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Loggers/Factories/ILoggerInitializerFactory.cs b/Lib.Logging/Loggers/Factories/ILoggerInitializerFactory.cs
new file mode 100644
index 0000000..1f2aae5
--- /dev/null
+++ b/Lib.Logging/Loggers/Factories/ILoggerInitializerFactory.cs
@@ -0,0 +1,14 @@
+// Author: Simon Gockner
+// Created: 2020-09-14
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using Lib.Logging.Interfaces;
+using Lib.Logging.Loggers.Interfaces;
+
+namespace Lib.Logging.Loggers.Factories
+{
+ public interface ILoggerInitializerFactory
+ {
+ ILoggerInitializer Create(ILog log);
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Loggers/FileLogger.cs b/Lib.Logging/Loggers/FileLogger.cs
new file mode 100644
index 0000000..d37b6d3
--- /dev/null
+++ b/Lib.Logging/Loggers/FileLogger.cs
@@ -0,0 +1,80 @@
+// Author: Gockner, Simon
+// Created: 2019-09-26
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Lib.Logging.Interfaces;
+using Lib.Logging.Loggers.Interfaces;
+
+namespace Lib.Logging.Loggers
+{
+ ///
+ /// An that writes log messages to a set file
+ ///
+ public class FileLogger : IFileLogger
+ {
+ private readonly StreamWriter _fileWriter;
+ private readonly Timer _timer;
+
+ private readonly SemaphoreSlim _lockObject = new SemaphoreSlim(1);
+
+ ///
+ /// Constructor for
+ ///
+ /// The directory of the LogFile
+ /// The path of the LogFile
+ public FileLogger(string filePath, string fileName)
+ {
+ Directory.CreateDirectory(filePath);
+ _fileWriter = new StreamWriter(Path.Combine(filePath, fileName), true);
+ _timer = new Timer(TimerCallback, null, 0, 1000);
+ }
+
+ ///
+ /// Write the given to the file
+ ///
+ /// The
+ public async Task Write(ILogMessage message)
+ {
+ await _lockObject.WaitAsync();
+ try
+ {
+ await _fileWriter.WriteAsync(message.ToString());
+ }
+ finally
+ {
+ _lockObject.Release();
+ }
+ }
+
+ private async void TimerCallback(object state) => await Flush();
+
+ private async Task Flush()
+ {
+ await _lockObject.WaitAsync();
+ try
+ {
+ await _fileWriter.FlushAsync();
+ }
+ finally
+ {
+ _lockObject.Release();
+ }
+ }
+
+ ///
+ /// the
+ ///
+ public async ValueTask DisposeAsync()
+ {
+ await _timer.DisposeAsync();
+
+ await Flush();
+ await _fileWriter.DisposeAsync();
+
+ _lockObject.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Loggers/Interfaces/IConsoleLogger.cs b/Lib.Logging/Loggers/Interfaces/IConsoleLogger.cs
new file mode 100644
index 0000000..96708ca
--- /dev/null
+++ b/Lib.Logging/Loggers/Interfaces/IConsoleLogger.cs
@@ -0,0 +1,11 @@
+// Author: Gockner, Simon
+// Created: 2019-11-24
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+namespace Lib.Logging.Loggers.Interfaces
+{
+ public interface IConsoleLogger : ILogger
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Loggers/Interfaces/IFileLogger.cs b/Lib.Logging/Loggers/Interfaces/IFileLogger.cs
new file mode 100644
index 0000000..225b767
--- /dev/null
+++ b/Lib.Logging/Loggers/Interfaces/IFileLogger.cs
@@ -0,0 +1,11 @@
+// Author: Gockner, Simon
+// Created: 2019-11-24
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+namespace Lib.Logging.Loggers.Interfaces
+{
+ public interface IFileLogger : ILogger
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Loggers/Interfaces/ILogger.cs b/Lib.Logging/Loggers/Interfaces/ILogger.cs
new file mode 100644
index 0000000..3684867
--- /dev/null
+++ b/Lib.Logging/Loggers/Interfaces/ILogger.cs
@@ -0,0 +1,22 @@
+// Author: Gockner, Simon
+// Created: 2019-09-26
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+using System.Threading.Tasks;
+using Lib.Logging.Interfaces;
+
+namespace Lib.Logging.Loggers.Interfaces
+{
+ ///
+ /// Base class for loggers
+ ///
+ public interface ILogger : IAsyncDisposable
+ {
+ ///
+ /// Write the given
+ ///
+ /// The
+ Task Write(ILogMessage message);
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Loggers/Interfaces/ILoggerInitializer.cs b/Lib.Logging/Loggers/Interfaces/ILoggerInitializer.cs
new file mode 100644
index 0000000..d7229e6
--- /dev/null
+++ b/Lib.Logging/Loggers/Interfaces/ILoggerInitializer.cs
@@ -0,0 +1,13 @@
+// Author: Simon Gockner
+// Created: 2020-09-14
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+
+namespace Lib.Logging.Loggers.Interfaces
+{
+ public interface ILoggerInitializer : IAsyncDisposable
+ {
+ bool Init();
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Loggers/LoggerInitializer.cs b/Lib.Logging/Loggers/LoggerInitializer.cs
new file mode 100644
index 0000000..152bf4a
--- /dev/null
+++ b/Lib.Logging/Loggers/LoggerInitializer.cs
@@ -0,0 +1,53 @@
+// Author: Simon Gockner
+// Created: 2020-09-14
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using Lib.Logging.Interfaces;
+using Lib.Logging.Loggers.Factories;
+using Lib.Logging.Loggers.Interfaces;
+
+namespace Lib.Logging.Loggers
+{
+ public class LoggerInitializer : ILoggerInitializer
+ {
+ private readonly string _logFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Mystify", "Logs");
+ private readonly string _logFileName = $"Mystify_Log_{DateTime.Now:yyyy_MM_dd}_{DateTime.Now:hh_mm_ss}.txt";
+
+ private readonly ILog _log;
+ private readonly IFileLoggerFactory _fileLoggerFactory;
+ private readonly IConsoleLoggerFactory _consoleLoggerFactory;
+
+ private IFileLogger? _fileLogger;
+ private IConsoleLogger? _consoleLogger;
+
+ public LoggerInitializer(ILog log, IFileLoggerFactory fileLoggerFactory, IConsoleLoggerFactory consoleLoggerFactory)
+ {
+ _log = log;
+ _fileLoggerFactory = fileLoggerFactory;
+ _consoleLoggerFactory = consoleLoggerFactory;
+ }
+
+ public bool Init()
+ {
+ _fileLogger = _fileLoggerFactory.Create(_logFilePath, _logFileName);
+ _log.AddLogger(_fileLogger);
+
+ _consoleLogger = _consoleLoggerFactory.Create();
+ _log.AddLogger(_consoleLogger);
+
+ return true;
+ }
+
+ public async ValueTask DisposeAsync()
+ {
+ if (_fileLogger != null)
+ await _fileLogger.DisposeAsync();
+
+ if (_consoleLogger != null)
+ await _consoleLogger.DisposeAsync();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Lib.Logging/Properties/AssemblyInfo.cs b/Lib.Logging/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ff6bf67
--- /dev/null
+++ b/Lib.Logging/Properties/AssemblyInfo.cs
@@ -0,0 +1,12 @@
+// Author: Simon Gockner
+// Created: 2020-09-18
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using Lib.Logging;
+
+[assembly:LogComponent("LOGGING")]
+
+namespace Lib.Logging.Properties
+{
+
+}
\ No newline at end of file
diff --git a/Lib.Tools/Enumerables.cs b/Lib.Tools/Enumerables.cs
new file mode 100644
index 0000000..620aa76
--- /dev/null
+++ b/Lib.Tools/Enumerables.cs
@@ -0,0 +1,29 @@
+// Author: Gockner, Simon
+// Created: 2020-11-20
+// Copyright(c) 2020 SimonG. All Rights Reserved.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+
+namespace Lib.Tools
+{
+ public static class Enumerables
+ {
+ public static ObservableCollection ToObservableCollection(this IEnumerable enumerable) => new ObservableCollection(enumerable);
+ public static ObservableCollection ToObservableCollectionOfType(this IEnumerable enumerable) => enumerable.Cast().ToObservableCollection();
+
+ public static IEnumerable ForEach(this IEnumerable enumerable, Action action)
+ {
+ IEnumerable list = enumerable.ToList();
+ foreach (T item in list)
+ {
+ action(item);
+ }
+
+ return list;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Lib.Tools/Lib.Tools.csproj b/Lib.Tools/Lib.Tools.csproj
new file mode 100644
index 0000000..61fcaf9
--- /dev/null
+++ b/Lib.Tools/Lib.Tools.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net5.0
+ 9
+ enable
+
+
+
diff --git a/Lib.Tools/Versions.cs b/Lib.Tools/Versions.cs
new file mode 100644
index 0000000..9b16c75
--- /dev/null
+++ b/Lib.Tools/Versions.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Reflection;
+
+namespace Lib.Tools
+{
+ public static class Versions
+ {
+ public static Version? GetVersion() => Assembly.GetEntryAssembly()?.GetName().Version;
+ }
+}
\ No newline at end of file
diff --git a/Mystify.sln b/Mystify.sln
index 08818f6..421cefb 100644
--- a/Mystify.sln
+++ b/Mystify.sln
@@ -10,6 +10,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib.Midi", "Lib.Midi\Lib.Mi
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib.Driver", "Lib.Driver\Lib.Driver.csproj", "{3C246E60-EC2B-41FE-AB1C-96B8C4FD9136}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib.Logging", "Lib.Logging\Lib.Logging.csproj", "{43547EFB-2525-41C6-846B-927C0AA058F7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lib.Tools", "Lib.Tools\Lib.Tools.csproj", "{4E283FDE-3E28-49F6-9FCF-529D8E82FBB9}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -36,5 +40,13 @@ Global
{3C246E60-EC2B-41FE-AB1C-96B8C4FD9136}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3C246E60-EC2B-41FE-AB1C-96B8C4FD9136}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3C246E60-EC2B-41FE-AB1C-96B8C4FD9136}.Release|Any CPU.Build.0 = Release|Any CPU
+ {43547EFB-2525-41C6-846B-927C0AA058F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {43547EFB-2525-41C6-846B-927C0AA058F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {43547EFB-2525-41C6-846B-927C0AA058F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {43547EFB-2525-41C6-846B-927C0AA058F7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4E283FDE-3E28-49F6-9FCF-529D8E82FBB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4E283FDE-3E28-49F6-9FCF-529D8E82FBB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4E283FDE-3E28-49F6-9FCF-529D8E82FBB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4E283FDE-3E28-49F6-9FCF-529D8E82FBB9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/Mystify/Enumerables.cs b/Mystify/Enumerables.cs
deleted file mode 100644
index 1b75b98..0000000
--- a/Mystify/Enumerables.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Author: Gockner, Simon
-// Created: 2021-04-14
-// Copyright(c) 2021 SimonG. All Rights Reserved.
-
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-
-namespace Mystify
-{
- public static class Enumerables
- {
- public static ObservableCollection ToObservableCollection(this IEnumerable enumerable) => new(enumerable);
- }
-}
\ No newline at end of file
diff --git a/Mystify/Mystify.csproj b/Mystify/Mystify.csproj
index 631c53e..dcc0704 100644
--- a/Mystify/Mystify.csproj
+++ b/Mystify/Mystify.csproj
@@ -19,5 +19,6 @@
+
diff --git a/Mystify/ViewModels/ControllableSelectionViewModel.cs b/Mystify/ViewModels/ControllableSelectionViewModel.cs
index 49df90c..f27b1e5 100644
--- a/Mystify/ViewModels/ControllableSelectionViewModel.cs
+++ b/Mystify/ViewModels/ControllableSelectionViewModel.cs
@@ -8,6 +8,7 @@ using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using Lib.Audio.Interfaces;
+using Lib.Tools;
using Mystify.Views;
using ReactiveUI;
diff --git a/Mystify/ViewModels/MainWindowViewModel.cs b/Mystify/ViewModels/MainWindowViewModel.cs
index 1666c90..8b2f635 100644
--- a/Mystify/ViewModels/MainWindowViewModel.cs
+++ b/Mystify/ViewModels/MainWindowViewModel.cs
@@ -9,6 +9,7 @@ using System.Linq;
using System.Windows.Input;
using Avalonia.Controls;
using Lib.Driver;
+using Lib.Tools;
using Mystify.Views;
using ReactiveUI;