Sfoglia il codice sorgente

initial layout, add followings:

qdr.app.qlbrc.console
qdr.app.qlbrc.base
qdr.app.qlbrc.common
qdr.fnd.core
qdr.fnd.core.business
qdr.fnd.core.data
qdr.fnd.core.data.itfc
qdr.fnd.core.nlog
qdr.fnd.core.qconsole
qdr.fnd.core.web

ready to work with
Dalibor Votruba 3 anni fa
parent
commit
62deacaeac
100 ha cambiato i file con 4811 aggiunte e 0 eliminazioni
  1. BIN
      Common/bo_strong_key_pair.snk
  2. 7 0
      Common/qdr.app.qlbrc.common/Class1.cs
  3. 9 0
      Common/qdr.app.qlbrc.common/qdr.app.qlbrc.common.csproj
  4. 83 0
      Common/qdr.fnd.core.business/AbstractMultiRepositoryService.cs
  5. 18 0
      Common/qdr.fnd.core.business/AbstractRepositoryService.cs
  6. 40 0
      Common/qdr.fnd.core.business/AbstractService.cs
  7. 129 0
      Common/qdr.fnd.core.business/Injection/DiManager.cs
  8. 9 0
      Common/qdr.fnd.core.business/Interface/IService.cs
  9. 68 0
      Common/qdr.fnd.core.business/Security/PasswordHelper.cs
  10. 21 0
      Common/qdr.fnd.core.business/qdr.fnd.core.business.csproj
  11. 9 0
      Common/qdr.fnd.core.data.itfc/Domain/IDomain.cs
  12. 7 0
      Common/qdr.fnd.core.data.itfc/Domain/IDomainContextResolver.cs
  13. 10 0
      Common/qdr.fnd.core.data.itfc/Domain/IUnitOfWork.cs
  14. 36 0
      Common/qdr.fnd.core.data.itfc/Entity/Dto/ErrorMessageDto.cs
  15. 41 0
      Common/qdr.fnd.core.data.itfc/Entity/Dto/ResultBoolDto.cs
  16. 52 0
      Common/qdr.fnd.core.data.itfc/Entity/Dto/ResultDto.cs
  17. 18 0
      Common/qdr.fnd.core.data.itfc/Entity/Dto/ResultPlain.cs
  18. 41 0
      Common/qdr.fnd.core.data.itfc/Entity/Dto/ResultValueDto.cs
  19. 30 0
      Common/qdr.fnd.core.data.itfc/Entity/Dto/ResultsValueDto.cs
  20. 9 0
      Common/qdr.fnd.core.data.itfc/Entity/IDao.cs
  21. 27 0
      Common/qdr.fnd.core.data.itfc/Entity/IDto.cs
  22. 18 0
      Common/qdr.fnd.core.data.itfc/Entity/IError.cs
  23. 25 0
      Common/qdr.fnd.core.data.itfc/Entity/IResult.cs
  24. 9 0
      Common/qdr.fnd.core.data.itfc/IPaging.cs
  25. 23 0
      Common/qdr.fnd.core.data.itfc/PagingDto.cs
  26. 21 0
      Common/qdr.fnd.core.data.itfc/Repository/IDaoRepository.cs
  27. 9 0
      Common/qdr.fnd.core.data.itfc/Repository/IRepository.cs
  28. 16 0
      Common/qdr.fnd.core.data.itfc/qdr.fnd.core.data.itfc.csproj
  29. 40 0
      Common/qdr.fnd.core.data/Domain/DataDomain.cs
  30. 21 0
      Common/qdr.fnd.core.data/Domain/DomainContextResolver.cs
  31. 26 0
      Common/qdr.fnd.core.data/Domain/UnitOfWork.cs
  32. 17 0
      Common/qdr.fnd.core.data/Domain/UnitOfWorkDataDomain.cs
  33. 27 0
      Common/qdr.fnd.core.data/Entity/Entity.cs
  34. 14 0
      Common/qdr.fnd.core.data/Entity/GuidEntity.cs
  35. 44 0
      Common/qdr.fnd.core.data/Entity/NoKey.cs
  36. 27 0
      Common/qdr.fnd.core.data/Extensions/ConnectionStringHelper.cs
  37. 27 0
      Common/qdr.fnd.core.data/Extensions/PagingExt.cs
  38. 19 0
      Common/qdr.fnd.core.data/Extensions/QueryableExt.cs
  39. 132 0
      Common/qdr.fnd.core.data/Extensions/SqlConnectionExt.cs
  40. 82 0
      Common/qdr.fnd.core.data/Mapper/Mapper.cs
  41. 57 0
      Common/qdr.fnd.core.data/Mapper/MapperExt.cs
  42. 15 0
      Common/qdr.fnd.core.data/Mapper/MapperGuid.cs
  43. 70 0
      Common/qdr.fnd.core.data/Mapper/MapperGuidExt.cs
  44. 50 0
      Common/qdr.fnd.core.data/Paging.cs
  45. 96 0
      Common/qdr.fnd.core.data/Repository/EntityRepository.cs
  46. 22 0
      Common/qdr.fnd.core.data/qdr.fnd.core.data.csproj
  47. 30 0
      Common/qdr.fnd.core.nlog/LogSeverityEnumExt.cs
  48. 43 0
      Common/qdr.fnd.core.nlog/Logger.cs
  49. 45 0
      Common/qdr.fnd.core.nlog/LoggerFactory.cs
  50. 21 0
      Common/qdr.fnd.core.nlog/qdr.fnd.core.nlog.csproj
  51. 90 0
      Common/qdr.fnd.core.qconsole/Argument/AbstractArgument.cs
  52. 23 0
      Common/qdr.fnd.core.qconsole/Argument/FlagArgument.cs
  53. 11 0
      Common/qdr.fnd.core.qconsole/Argument/NamedArgument.cs
  54. 23 0
      Common/qdr.fnd.core.qconsole/Argument/OrdinalArgument.cs
  55. 9 0
      Common/qdr.fnd.core.qconsole/Attributes/CommandDefinitionAttribute.cs
  56. 393 0
      Common/qdr.fnd.core.qconsole/Command/Base/AbstractCommand.cs
  57. 270 0
      Common/qdr.fnd.core.qconsole/Command/Base/AbstractListCommand.cs
  58. 127 0
      Common/qdr.fnd.core.qconsole/Command/Base/AbstractSelectionCommand.cs
  59. 11 0
      Common/qdr.fnd.core.qconsole/Command/Base/ISelectionEntry.cs
  60. 31 0
      Common/qdr.fnd.core.qconsole/Command/Defaults/CmdClear.cs
  61. 29 0
      Common/qdr.fnd.core.qconsole/Command/Defaults/CmdExit.cs
  62. 190 0
      Common/qdr.fnd.core.qconsole/Command/Defaults/CmdHelp.cs
  63. 87 0
      Common/qdr.fnd.core.qconsole/Command/Defaults/CmdPrint.cs
  64. 74 0
      Common/qdr.fnd.core.qconsole/Command/Defaults/CmdSelection.cs
  65. 234 0
      Common/qdr.fnd.core.qconsole/Configuration/StartupConfiguration.cs
  66. 128 0
      Common/qdr.fnd.core.qconsole/Constants.cs
  67. 18 0
      Common/qdr.fnd.core.qconsole/Context/DefaultCommandContext.cs
  68. 23 0
      Common/qdr.fnd.core.qconsole/Context/DefualtEngineContext.cs
  69. 6 0
      Common/qdr.fnd.core.qconsole/Context/ICommandContext.cs
  70. 7 0
      Common/qdr.fnd.core.qconsole/Context/IEngineContext.cs
  71. 9 0
      Common/qdr.fnd.core.qconsole/Context/IQConsoleContext.cs
  72. 36 0
      Common/qdr.fnd.core.qconsole/DebugConsoleWriter.cs
  73. 46 0
      Common/qdr.fnd.core.qconsole/Defaults.cs
  74. 321 0
      Common/qdr.fnd.core.qconsole/Engine.cs
  75. 21 0
      Common/qdr.fnd.core.qconsole/Extensions/AbstractArgumentExt.cs
  76. 4 0
      Common/qdr.fnd.core.qconsole/Handlers/General.cs
  77. 94 0
      Common/qdr.fnd.core.qconsole/Value/AbstractValue.cs
  78. 23 0
      Common/qdr.fnd.core.qconsole/Value/BoolValue.cs
  79. 26 0
      Common/qdr.fnd.core.qconsole/Value/DateTimeValue.cs
  80. 34 0
      Common/qdr.fnd.core.qconsole/Value/DateValue.cs
  81. 24 0
      Common/qdr.fnd.core.qconsole/Value/DecimalValue.cs
  82. 26 0
      Common/qdr.fnd.core.qconsole/Value/GuidValue.cs
  83. 25 0
      Common/qdr.fnd.core.qconsole/Value/IntegerValue.cs
  84. 26 0
      Common/qdr.fnd.core.qconsole/Value/StringValue.cs
  85. 18 0
      Common/qdr.fnd.core.qconsole/Value/TimeSpanValue.cs
  86. 22 0
      Common/qdr.fnd.core.qconsole/Value/TimeValue.cs
  87. 15 0
      Common/qdr.fnd.core.qconsole/Value/TypeValuesEnum.cs
  88. 18 0
      Common/qdr.fnd.core.qconsole/qdr.fnd.core.qconsole.csproj
  89. 90 0
      Common/qdr.fnd.core.web/Controllers/BaseController.cs
  90. 23 0
      Common/qdr.fnd.core.web/Extensions/DtoExt.cs
  91. 28 0
      Common/qdr.fnd.core.web/Logging/AutoLogAttribute.cs
  92. 22 0
      Common/qdr.fnd.core.web/qdr.fnd.core.web.csproj
  93. 6 0
      Common/qdr.fnd.core/Api/IApiClient.cs
  94. 23 0
      Common/qdr.fnd.core/Attributes/DiImplementsOfAttribute.cs
  95. 9 0
      Common/qdr.fnd.core/Attributes/DiModuleAttribute.cs
  96. 9 0
      Common/qdr.fnd.core/Attributes/LifeCycleTypeEnum.cs
  97. 84 0
      Common/qdr.fnd.core/Console/ConsoleWriter.cs
  98. 113 0
      Common/qdr.fnd.core/Console/ProgressBar.cs
  99. 78 0
      Common/qdr.fnd.core/Console/ProgressConsoleWriter.cs
  100. 44 0
      Common/qdr.fnd.core/Data/CsvHelper.cs

BIN
Common/bo_strong_key_pair.snk


+ 7 - 0
Common/qdr.app.qlbrc.common/Class1.cs

@@ -0,0 +1,7 @@
+namespace qdr.app.qlbrc.common
+{
+    public class Class1
+    {
+
+    }
+}

+ 9 - 0
Common/qdr.app.qlbrc.common/qdr.app.qlbrc.common.csproj

@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+</Project>

+ 83 - 0
Common/qdr.fnd.core.business/AbstractMultiRepositoryService.cs

@@ -0,0 +1,83 @@
+using System;
+using System.Security.Principal;
+using Microsoft.Extensions.Logging;
+using Quadarax.Foundation.Core.Data.Interface.Repository;
+
+namespace Quadarax.Foundation.Core.Business
+{
+    public abstract class AbstractMultiRepositoryService<TRepository1,TRepository2> : AbstractService 
+        where TRepository1: IRepository
+        where TRepository2: IRepository
+    {
+        protected TRepository1 Repository1 { get; }
+        protected TRepository2 Repository2 { get; }
+
+        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2,IPrincipal currentPrincipal,  ILoggerFactory logger) : base(currentPrincipal, logger)
+        {
+            Repository1 = repository1 ?? throw new ArgumentNullException(nameof(repository1));
+            Repository2 = repository2 ?? throw new ArgumentNullException(nameof(repository2));
+        }
+    }
+
+
+    public abstract class AbstractMultiRepositoryService<TRepository1,TRepository2, TRepository3> : AbstractService 
+        where TRepository1: IRepository
+        where TRepository2: IRepository
+        where TRepository3: IRepository
+    {
+        protected TRepository1 Repository1 { get; }
+        protected TRepository2 Repository2 { get; }
+        protected TRepository3 Repository3 { get; }
+
+        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2, TRepository3 repository3,IPrincipal currentPrincipal, ILoggerFactory logger) : base(currentPrincipal, logger)
+        {
+            Repository1 = repository1 ?? throw new ArgumentNullException(nameof(repository1));
+            Repository2 = repository2 ?? throw new ArgumentNullException(nameof(repository2));
+            Repository3 = repository3 ?? throw new ArgumentNullException(nameof(repository3));
+        }
+    }
+
+    public abstract class AbstractMultiRepositoryService<TRepository1,TRepository2, TRepository3, TRepository4> : AbstractService 
+        where TRepository1: IRepository
+        where TRepository2: IRepository
+        where TRepository3: IRepository
+        where TRepository4: IRepository
+    {
+        protected TRepository1 Repository1 { get; }
+        protected TRepository2 Repository2 { get; }
+        protected TRepository3 Repository3 { get; }
+        protected TRepository4 Repository4 { get; }
+
+        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2, TRepository3 repository3,TRepository4 repository4, IPrincipal currentPrincipal, ILoggerFactory logger) : base(currentPrincipal, logger)
+        {
+            Repository1 = repository1 ?? throw new ArgumentNullException(nameof(repository1));
+            Repository2 = repository2 ?? throw new ArgumentNullException(nameof(repository2));
+            Repository3 = repository3 ?? throw new ArgumentNullException(nameof(repository3));
+            Repository4 = repository4 ?? throw new ArgumentNullException(nameof(repository4));
+        }
+    }
+
+
+    public abstract class AbstractMultiRepositoryService<TRepository1,TRepository2, TRepository3, TRepository4, TRepository5> : AbstractService 
+        where TRepository1: IRepository
+        where TRepository2: IRepository
+        where TRepository3: IRepository
+        where TRepository4: IRepository
+        where TRepository5: IRepository
+    {
+        protected TRepository1 Repository1 { get; }
+        protected TRepository2 Repository2 { get; }
+        protected TRepository3 Repository3 { get; }
+        protected TRepository4 Repository4 { get; }
+        protected TRepository5 Repository5 { get; }
+
+        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2, TRepository3 repository3,TRepository4 repository4,TRepository5 repository5,IPrincipal currentPrincipal, ILoggerFactory logger) : base(currentPrincipal, logger)
+        {
+            Repository1 = repository1 ?? throw new ArgumentNullException(nameof(repository1));
+            Repository2 = repository2 ?? throw new ArgumentNullException(nameof(repository2));
+            Repository3 = repository3 ?? throw new ArgumentNullException(nameof(repository3));
+            Repository4 = repository4 ?? throw new ArgumentNullException(nameof(repository4));
+            Repository5 = repository5 ?? throw new ArgumentNullException(nameof(repository5));
+        }
+    }
+}

+ 18 - 0
Common/qdr.fnd.core.business/AbstractRepositoryService.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Security.Principal;
+using Microsoft.Extensions.Logging;
+using NLog;
+using Quadarax.Foundation.Core.Data.Interface.Repository;
+
+namespace Quadarax.Foundation.Core.Business
+{
+    public abstract class AbstractRepositoryService<TRepository> : AbstractService where TRepository: IRepository
+    {
+        protected TRepository Repository { get; }
+
+        protected AbstractRepositoryService(TRepository repository,IPrincipal currentPrincipal, ILoggerFactory logger) : base(currentPrincipal, logger)
+        {
+            Repository = repository ?? throw new ArgumentNullException(nameof(repository));
+        }
+    }
+}

+ 40 - 0
Common/qdr.fnd.core.business/AbstractService.cs

@@ -0,0 +1,40 @@
+using System;
+using System.Security.Principal;
+using Microsoft.Extensions.Logging;
+using Quadarax.Foundation.Core.Business.Interface;
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+using Quadarax.Foundation.Core.Data.Interface.Entity.Dto;
+
+namespace Quadarax.Foundation.Core.Business
+{
+    public abstract class AbstractService : IService
+    {
+        #region *** Properties ***
+        protected ILogger<AbstractService> Log { get; }
+        protected IPrincipal CurrentPrincipal { get; }
+        #endregion
+
+        #region *** Constructors ***
+        protected AbstractService(IPrincipal currentPrincipal, ILoggerFactory logger)
+        {
+            Log = logger.CreateLogger<AbstractService>();
+
+            if (currentPrincipal == null)
+            {
+                var genericIdentity = new GenericIdentity("genericIdentity");
+                currentPrincipal = new GenericPrincipal(genericIdentity, new string[] {});
+            }
+            CurrentPrincipal = currentPrincipal;
+            Log.LogTrace($"Service '{GetType().Name}' [Hash:{GetHashCode()}] initialized.");
+        }
+        #endregion
+
+        #region *** Public Operations ***
+        public IResult Test()
+        {
+            return new ResultPlain();
+        }
+
+        #endregion
+    }
+}

+ 129 - 0
Common/qdr.fnd.core.business/Injection/DiManager.cs

@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Reflection;
+using Microsoft.Extensions.DependencyInjection;
+using NLog;
+using Quadarax.Foundation.Core.Attributes;
+using Quadarax.Foundation.Core.Reflection;
+using Quadarax.Foundation.Core.Reflection.Extensions;
+using ILogger = NLog.ILogger;
+
+namespace Quadarax.Foundation.Core.Business.Injection
+{
+    /// <summary>
+    /// Register modules inside defined assemblies. Modules must be flagged by <see cref="DiModuleAttribute"/> and <see cref="DiImplementsOfAttribute"/>
+    /// </summary>
+    public static class DiManager
+    {
+        #region *** Private fields ***
+        private static IList<Assembly> _registeredAssemblies = new List<Assembly>();
+        private static ILogger _logger = LogManager.GetLogger(nameof(DiManager));
+        #endregion
+
+        #region *** Public properties ***
+        public static string[] RegisteredAssembliesNames =>
+            _registeredAssemblies.Select(x => x.GetName().ToString()).ToArray();
+        #endregion 
+
+        #region  *** Public Operations ***
+        /// <summary>
+        /// Register all assemblies from current appdomain.
+        /// </summary>
+        public static void RegisterAssemblyFromThisAppdomain()
+        {
+            RegisterAssemblyFromThisAppdomain(null, null);
+        }
+        /// <summary>
+        /// Register all assemblies from current appdomain by filtering options.
+        /// </summary>
+        /// <param name="includedStartsWith"></param>
+        /// <param name="excludedStartsWith"></param>
+        public static void RegisterAssemblyFromThisAppdomain([AllowNull]IEnumerable<string> includedStartsWith,[AllowNull] IEnumerable<string> excludedStartsWith)
+        {
+            includedStartsWith ??= new List<string>();
+            excludedStartsWith ??= new List<string>();
+
+            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
+            {
+                var isRegister = includedStartsWith.Any() && includedStartsWith.Any(x => assembly.GetName().ToString().StartsWith(x));
+                isRegister = isRegister && !excludedStartsWith.Any(x => assembly.GetName().ToString().StartsWith(x));
+                if (isRegister)
+                    RegisterAssembly(assembly);
+            }
+        }
+
+
+        /// <summary>
+        /// Register an assembly to scan and find modules flagged by <see cref="DiModuleAttribute"/>
+        /// </summary>
+        /// <param name="assembly"></param>
+        public static void RegisterAssembly([NotNull]Assembly assembly)
+        {
+            if (assembly == null)
+                throw new ArgumentNullException(nameof(assembly));
+
+            if (_registeredAssemblies.Contains(assembly)) 
+                return;
+
+            _registeredAssemblies.Add(assembly);
+            var logMessage = $"DiManager register assembly: {assembly.GetName()}";
+            _logger.Debug(logMessage);
+            Trace.WriteLine(logMessage,"DI");
+        }
+
+        /// <summary>
+        /// Scans registered assemblies and register them to <see cref="IServiceCollection"/>
+        /// </summary>
+        /// <param name="services">Service definition collection.</param>
+        public static void ScanAndRegisterDependencyInjections([NotNull]IServiceCollection services)
+        {
+            int cntAssemblies = 0;
+            int cntTypes = 0;
+            int cntRegistrations = 0;
+            foreach (var assembly in _registeredAssemblies)
+            {
+                cntAssemblies++;
+                var logMessage = $"Scanning assembly '{assembly.GetName()}' ...";
+                _logger.Debug(logMessage);
+                Trace.WriteLine(logMessage,"DI");
+                var types = assembly.GetTypesWithAttribute<DiModuleAttribute>(true);
+                foreach (var type in types)
+                {
+                    cntTypes++;
+                    var attributes = AttributeQuery<DiImplementsOfAttribute>.FindAll(type);
+                    foreach (var attribute in attributes)
+                    {
+                        switch (attribute.LifeCycleType)
+                        {
+                            case LifeCycleTypeEnum.Scoped:
+                                services.AddScoped(attribute.InterfaceTypeImplementing, type);
+                                break;
+                            case LifeCycleTypeEnum.Singleton:
+                                services.AddSingleton(attribute.InterfaceTypeImplementing, type);
+                                break;
+                            case LifeCycleTypeEnum.Transient:
+                                services.AddTransient(attribute.InterfaceTypeImplementing, type);
+                                break;
+                            default:
+                                throw new NotSupportedException($"Not supported registration for LifeCycleType = {attribute.LifeCycleType}");
+                        }
+
+                        cntRegistrations++;
+                        logMessage = $"DI registered: Type={attribute.InterfaceTypeImplementing.FullName} for Type={type.Name} as LifeCycle={attribute.LifeCycleType}";
+                        _logger.Info(logMessage);
+                        Trace.WriteLine(logMessage,"DI");
+
+                    }
+                }
+            }
+            var logMessage2 = $"DI registered. Assemblies={cntAssemblies}, Types={cntTypes}, Registrations={cntRegistrations}.";
+            _logger.Info(logMessage2);
+            Trace.WriteLine(logMessage2,"DI");
+
+        }
+        #endregion
+    }
+}

+ 9 - 0
Common/qdr.fnd.core.business/Interface/IService.cs

@@ -0,0 +1,9 @@
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+
+namespace Quadarax.Foundation.Core.Business.Interface
+{
+    public interface IService
+    {
+        IResult Test();
+    }
+}

+ 68 - 0
Common/qdr.fnd.core.business/Security/PasswordHelper.cs

@@ -0,0 +1,68 @@
+using System;
+using System.Security.Cryptography;
+
+namespace Quadarax.Foundation.Core.Business.Security
+{
+    public static class PasswordHelper
+    {
+        public static string HashPassword(string password)
+        {
+            byte[] salt;
+            byte[] buffer2;
+            if (password == null)
+            {
+                throw new ArgumentNullException("password");
+            }
+            using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, 0x10, 0x3e8))
+            {
+                salt = bytes.Salt;
+                buffer2 = bytes.GetBytes(0x20);
+            }
+            byte[] dst = new byte[0x31];
+            Buffer.BlockCopy(salt, 0, dst, 1, 0x10);
+            Buffer.BlockCopy(buffer2, 0, dst, 0x11, 0x20);
+            return Convert.ToBase64String(dst);
+        }
+
+        public static bool VerifyHashedPassword(string hashedPassword, string password)
+        {
+            byte[] buffer4;
+            if (hashedPassword == null)
+            {
+                return false;
+            }
+            if (password == null)
+            {
+                throw new ArgumentNullException("password");
+            }
+            byte[] src = Convert.FromBase64String(hashedPassword);
+            if ((src.Length != 0x31) || (src[0] != 0))
+            {
+                return false;
+            }
+            byte[] dst = new byte[0x10];
+            Buffer.BlockCopy(src, 1, dst, 0, 0x10);
+            byte[] buffer3 = new byte[0x20];
+            Buffer.BlockCopy(src, 0x11, buffer3, 0, 0x20);
+            using (Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(password, dst, 0x3e8))
+            {
+                buffer4 = bytes.GetBytes(0x20);
+            }
+            return ByteArraysEqual(buffer3, buffer4);
+        }
+
+        private static bool ByteArraysEqual(byte[] b1, byte[] b2)
+        {
+            if (b1 == b2) return true;
+            if (b1 == null || b2 == null) return false;
+            if (b1.Length != b2.Length) return false;
+            for (int i=0; i < b1.Length; i++)
+            {
+                if (b1[i] != b2[i]) return false;
+            }
+            return true;
+        }
+    }
+
+
+}

+ 21 - 0
Common/qdr.fnd.core.business/qdr.fnd.core.business.csproj

@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>..\bo_strong_key_pair.snk</AssemblyOriginatorKeyFile>
+    <DelaySign>false</DelaySign>
+    <RootNamespace>Quadarax.Foundation.Core.Business</RootNamespace>
+    <ApplicationIcon>..\quadarax_dll.ico</ApplicationIcon>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\qdr.fnd.core.data\qdr.fnd.core.data.csproj" />
+    <ProjectReference Include="..\qdr.fnd.core\qdr.fnd.core.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="NLog" Version="5.0.4" />
+  </ItemGroup>
+
+</Project>

+ 9 - 0
Common/qdr.fnd.core.data.itfc/Domain/IDomain.cs

@@ -0,0 +1,9 @@
+namespace Quadarax.Foundation.Core.Data.Interface.Domain
+{
+    public interface IDomain
+    {
+        TEntitySet GetDbSet<TEntitySet>();
+        IUnitOfWork<TDomainContext> CreateUnitOfWork<TDomainContext>() where TDomainContext : IDomain;
+        void Commit();
+    }
+}

+ 7 - 0
Common/qdr.fnd.core.data.itfc/Domain/IDomainContextResolver.cs

@@ -0,0 +1,7 @@
+namespace Quadarax.Foundation.Core.Data.Interface.Domain
+{
+    public interface IDomainContextResolver<TDomainContext> where TDomainContext : IDomain
+    {
+        TReturnContext GetCurrent<TReturnContext>() where TReturnContext : TDomainContext;
+    }
+}

+ 10 - 0
Common/qdr.fnd.core.data.itfc/Domain/IUnitOfWork.cs

@@ -0,0 +1,10 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Domain
+{
+    public interface IUnitOfWork<TDomainContext> : IDisposable where TDomainContext : IDomain
+    {
+        TDomainContext Context { get;  }
+        void Commit();
+    }
+}

+ 36 - 0
Common/qdr.fnd.core.data.itfc/Entity/Dto/ErrorMessageDto.cs

@@ -0,0 +1,36 @@
+using System;
+using Quadarax.Foundation.Core.Exceptions;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Entity.Dto
+{
+    public class ErrorMessageDto : IDto, IError
+    {
+        /// <summary>
+        /// <inheritdoc cref="IError.Message"/>
+        /// </summary>
+        public string Message { get; set; }
+        /// <summary>
+        /// <inheritdoc cref="IError.Code"/>
+        /// </summary>
+        public int Code { get; set; }
+
+        public ErrorMessageDto(){}
+        public ErrorMessageDto(Exception exception, int code)
+        {
+            if (exception==null)
+                throw new ArgumentNullException(nameof(exception));
+
+            Message = exception.Message;
+            Code = code;
+        }
+
+        public ErrorMessageDto(CodeException exception)
+        {
+            if (exception==null)
+                throw new ArgumentNullException(nameof(exception));
+
+            Message = exception.Message;
+            Code = exception.GetCode();
+        }
+    }
+}

+ 41 - 0
Common/qdr.fnd.core.data.itfc/Entity/Dto/ResultBoolDto.cs

@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json.Serialization;
+using Quadarax.Foundation.Core.Exceptions;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Entity.Dto
+{
+    public class ResultBoolDto : ResultDto
+    {
+        [JsonPropertyName("value")]
+        public bool Value { get; set; }
+
+
+        public ResultBoolDto(bool value) : this()
+        {
+            Value = value;
+        }
+
+        public ResultBoolDto() : base(new List<IError>())
+        {
+            Value = false;
+        }
+        public ResultBoolDto(CodeException[] exceptions) : base(exceptions.Select(x => new ErrorMessageDto(x)))
+        {
+        }
+
+        public ResultBoolDto(Exception exception) : base( new []{ exception is CodeException codeException ? new ErrorMessageDto(codeException) : new ErrorMessageDto(exception, -1)})
+        {
+        }
+
+        public override object GetValue()
+        {
+            return Value;
+        }
+        public bool GetValueAs()
+        {
+            return Value;
+        }
+    }
+}

+ 52 - 0
Common/qdr.fnd.core.data.itfc/Entity/Dto/ResultDto.cs

@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Quadarax.Foundation.Core.Exceptions;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Entity.Dto
+{
+    public abstract class ResultDto : IDto, IResult
+    {
+        /// <summary>
+        /// <inheritdoc cref="IResult.IsSuccess"/>
+        /// </summary>
+        public bool IsSuccess => !Errors.Any();
+        /// <summary>
+        /// <inheritdoc cref="IResult.Errors"/>
+        /// </summary>
+        public IEnumerable<ErrorMessageDto> Errors { get; set; }
+        //public IEnumerable<IError> Errors { get; set; }
+
+        IEnumerable<IError> IResult.Errors => Errors;
+
+        /// <summary>
+        /// <inheritdoc cref="IResult.GetValue()"/>
+        /// </summary>
+        /// <returns></returns>
+        public abstract object GetValue();
+
+        protected ResultDto(IEnumerable<IError> errors)
+        {
+             Errors = new List<ErrorMessageDto>(errors.Select(x=>(ErrorMessageDto) x));
+            //Errors = new List<IError>(errors);
+        }
+        protected ResultDto()
+        {
+            Errors = new List<ErrorMessageDto>();
+        }
+        public AggregateException ToAggregateException()
+        {
+            if (IsSuccess)
+                return null;
+            var errors = new List<Exception>();
+            foreach (var e in Errors)
+            {
+                var addExc = new Exception(e.Message);
+                addExc.SetCode(e.Code);
+                errors.Add(addExc);
+            }
+            return new AggregateException(errors);
+        }
+        
+    }
+}

+ 18 - 0
Common/qdr.fnd.core.data.itfc/Entity/Dto/ResultPlain.cs

@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Entity.Dto
+{
+    public class ResultPlain : ResultDto
+    {
+        public override object GetValue()
+        {
+            return null;
+        }
+
+        public ResultPlain(){}
+
+        public ResultPlain(IEnumerable<IError> errors) : base(errors)
+        {
+        }
+    }
+}

+ 41 - 0
Common/qdr.fnd.core.data.itfc/Entity/Dto/ResultValueDto.cs

@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json.Serialization;
+using Quadarax.Foundation.Core.Exceptions;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Entity.Dto
+{
+    public class ResultValueDto<TDto> : ResultDto where TDto : IDto, new()
+    {
+        [JsonPropertyName("value")]
+        public TDto Value { get; set; }
+
+
+        public ResultValueDto(TDto value) : this()
+        {
+            Value = value;
+        }
+
+        public ResultValueDto() : base(new List<IError>())
+        {
+            Value = new TDto();
+        }
+        public ResultValueDto(CodeException[] exceptions) : base(exceptions.Select(x => new ErrorMessageDto(x)))
+        {
+        }
+
+        public ResultValueDto(Exception exception) : base( new []{ exception is CodeException codeException ? new ErrorMessageDto(codeException) : new ErrorMessageDto(exception, -1)})
+        {
+        }
+
+        public override object GetValue()
+        {
+            return Value;
+        }
+        public TDto GetValueAs()
+        {
+            return Value;
+        }
+    }
+}

+ 30 - 0
Common/qdr.fnd.core.data.itfc/Entity/Dto/ResultsValueDto.cs

@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Entity.Dto
+{
+    public class ResultsValueDto<TDto> : ResultDto where TDto : IDto
+    {
+        [JsonPropertyName("values")]
+        public IEnumerable<TDto> Values { get; set; }
+
+
+        public ResultsValueDto()
+        {
+            Values = new List<TDto>();
+        }
+        public ResultsValueDto(IEnumerable<TDto> values)
+        {
+            Values = values;
+        }
+
+        public override object GetValue()
+        {
+            return Values;
+        }
+        public IEnumerable<TDto> GetValueAs()
+        {
+            return Values;
+        }
+    }
+}

+ 9 - 0
Common/qdr.fnd.core.data.itfc/Entity/IDao.cs

@@ -0,0 +1,9 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Entity
+{
+    public interface IDao<TKey> where TKey : IEquatable<TKey>
+    {
+        public TKey Id { get; set; }
+    }
+}

+ 27 - 0
Common/qdr.fnd.core.data.itfc/Entity/IDto.cs

@@ -0,0 +1,27 @@
+namespace Quadarax.Foundation.Core.Data.Interface.Entity
+{
+    public interface IDto
+    {
+    }
+
+    public interface ICreateDto : IModifyDto
+    {
+    }
+
+    public interface IDeleteDto : IDto
+    {
+    }
+
+    public interface IUpdateDto : IModifyDto
+    {
+    }
+
+    public interface IReadDto : IDto
+    {
+    }
+
+    public interface IModifyDto : IDto
+    {
+        
+    }
+}

+ 18 - 0
Common/qdr.fnd.core.data.itfc/Entity/IError.cs

@@ -0,0 +1,18 @@
+namespace Quadarax.Foundation.Core.Data.Interface.Entity
+{
+
+    /// <summary>
+    /// Defines error message structure
+    /// </summary>
+    public interface IError
+    {
+        /// <summary>
+        /// Full error message
+        /// </summary>
+        public string Message { get; }
+        /// <summary>
+        /// Error message short numeric code
+        /// </summary>
+        public int Code { get; }
+    }
+}

+ 25 - 0
Common/qdr.fnd.core.data.itfc/Entity/IResult.cs

@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Entity
+{
+    /// <summary>
+    /// Represents structure of result state
+    /// </summary>
+    public interface IResult
+    {
+        /// <summary>
+        /// Gets if result is logically success
+        /// </summary>
+        bool IsSuccess { get; }
+        /// <summary>
+        /// Collection of error items
+        /// </summary>
+        public IEnumerable<IError> Errors { get; }
+
+        /// <summary>
+        /// Returns result value
+        /// </summary>
+        /// <returns>Value</returns>
+        public object GetValue();
+    }
+}

+ 9 - 0
Common/qdr.fnd.core.data.itfc/IPaging.cs

@@ -0,0 +1,9 @@
+namespace Quadarax.Foundation.Core.Data.Interface
+{
+    public interface IPaging
+    {
+        int Page { get; }
+        int PageSize { get; }
+        bool IsDisabled { get; }
+    }
+}

+ 23 - 0
Common/qdr.fnd.core.data.itfc/PagingDto.cs

@@ -0,0 +1,23 @@
+namespace Quadarax.Foundation.Core.Data.Interface
+{
+    public class PagingDto : IPaging
+    {
+        public PagingDto()
+        {
+            IsDisabled = true;
+        }
+
+        public PagingDto(int page, int pageSize)
+        {
+            IsDisabled = true;
+            Page = page;
+            PageSize = pageSize;
+            IsDisabled = false;
+        }
+
+        public int Page { get; protected set; }
+        public int PageSize { get; protected set;}
+        public bool IsDisabled { get; protected set; }
+
+    }
+}

+ 21 - 0
Common/qdr.fnd.core.data.itfc/Repository/IDaoRepository.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Repository
+{
+    public interface IDaoRepository<TKey, TDao> : IRepository where TDao : IDao<TKey> where TKey : IEquatable<TKey>
+    {
+        public IQueryable<TDao> Query(IPaging paging, bool usingUncomited = false);
+        public TDao Get(TKey id);
+        public IQueryable<TDao> Get(IEnumerable<TKey> ids);
+        public TDao Set(TDao entity);
+        public IEnumerable<TDao> Set(IEnumerable<TDao> entities);
+        public TDao New();
+        public bool Remove(TKey id);
+        public IEnumerable<bool> Remove(IEnumerable<TKey> ids);
+        public bool Remove(TDao entity);
+        public IEnumerable<bool> Remove(IEnumerable<TDao> entities);
+    }
+}

+ 9 - 0
Common/qdr.fnd.core.data.itfc/Repository/IRepository.cs

@@ -0,0 +1,9 @@
+using System.Transactions;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Repository
+{
+    public interface IRepository
+    {
+        void Commit();
+    }
+}

+ 16 - 0
Common/qdr.fnd.core.data.itfc/qdr.fnd.core.data.itfc.csproj

@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>..\bo_strong_key_pair.snk</AssemblyOriginatorKeyFile>
+    <DelaySign>false</DelaySign>
+    <RootNamespace>Quadarax.Foundation.Core.Data.Interface</RootNamespace>
+    <ApplicationIcon>..\quadarax_dll.ico</ApplicationIcon>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\qdr.fnd.core\qdr.fnd.core.csproj" />
+  </ItemGroup>
+
+</Project>

+ 40 - 0
Common/qdr.fnd.core.data/Domain/DataDomain.cs

@@ -0,0 +1,40 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using Microsoft.EntityFrameworkCore;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+
+namespace Quadarax.Foundation.Core.Data.Domain
+{
+    public abstract class DataDomain : DbContext, IDomain
+    {
+        private MethodInfo _mtSet;
+        private MethodInfo _mtgSet;
+        protected DataDomain(DbContextOptions options) : base(options)
+        {
+
+        }
+        public TEntitySet GetDbSet<TEntitySet>()
+        {
+            //TODO: comment because db constext is in this scope static
+            //if (_mtSet == null)
+                _mtSet = GetType().GetMethod(nameof(DbContext.Set), Type.EmptyTypes);//GetType().GetMethod("Set");
+            //if (_mtgSet==null)
+                _mtgSet = _mtSet.MakeGenericMethod(typeof(TEntitySet).GetGenericArguments().First());
+
+            var returnValue = _mtgSet.Invoke(this, new object[] {});
+            return (TEntitySet)returnValue;
+        }
+
+        public IUnitOfWork<TDomainContext> CreateUnitOfWork<TDomainContext>() where TDomainContext : IDomain
+        {
+            return new UnitOfWork<TDomainContext>((IDomainContextResolver<TDomainContext>)new DomainContextResolver<DataDomain>(this));
+        }
+
+
+        public void Commit()
+        {
+            this.SaveChanges();
+        }
+    }     
+}

+ 21 - 0
Common/qdr.fnd.core.data/Domain/DomainContextResolver.cs

@@ -0,0 +1,21 @@
+using System;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+
+namespace Quadarax.Foundation.Core.Data.Domain
+{
+    public class DomainContextResolver<TDomainContext> : IDomainContextResolver<TDomainContext> where TDomainContext: DataDomain
+    {
+        private TDomainContext _context;
+
+        public DomainContextResolver(TDomainContext context)
+        {
+            _context = context ?? throw new ArgumentNullException(nameof(context));
+        }
+
+
+        public TReturnContext GetCurrent<TReturnContext>() where TReturnContext : TDomainContext
+        {
+            return (TReturnContext) _context;
+        }
+    }
+}

+ 26 - 0
Common/qdr.fnd.core.data/Domain/UnitOfWork.cs

@@ -0,0 +1,26 @@
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+using Quadarax.Foundation.Core.Object;
+
+namespace Quadarax.Foundation.Core.Data.Domain
+{
+    public class UnitOfWork<TDomainContext> : DisposableObject,  IUnitOfWork<TDomainContext> where TDomainContext : IDomain
+    {
+
+        public TDomainContext Context { get; protected set; }
+
+        public UnitOfWork(IDomainContextResolver<TDomainContext> context)
+        {
+            Context = context.GetCurrent<TDomainContext>();
+        }
+
+        public void Commit()
+        {
+            Context.Commit();
+        }
+
+        protected override void OnDisposing()
+        {
+            Context = default;
+        }
+    }
+}

+ 17 - 0
Common/qdr.fnd.core.data/Domain/UnitOfWorkDataDomain.cs

@@ -0,0 +1,17 @@
+using Quadarax.Foundation.Core.Attributes;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+
+namespace Quadarax.Foundation.Core.Data.Domain
+{
+    //[DiModule]
+    //[DiImplementsOf(typeof(IUnitOfWork<IDomain>), LifeCycleTypeEnum.Scoped)]
+    //[DiImplementsOf(typeof(IUnitOfWork<DataDomain>), LifeCycleTypeEnum.Scoped)]
+    public class UnitOfWorkDataDomain : UnitOfWork<DataDomain>, IUnitOfWork<IDomain>
+    {
+        public UnitOfWorkDataDomain(IDomainContextResolver<DataDomain> context) : base(context)
+        {
+        }
+
+        IDomain IUnitOfWork<IDomain>.Context => Context;
+    }
+}

+ 27 - 0
Common/qdr.fnd.core.data/Entity/Entity.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Text;
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+
+namespace Quadarax.Foundation.Core.Data.Entity
+{
+    public abstract class Entity<TKey> : IDao<TKey> where TKey : IEquatable<TKey>
+    {
+        #region *** Properties ***
+
+        public virtual TKey Id { get; set; }
+
+        #endregion
+
+        #region *** Public Overrides ***
+
+        public override string ToString()
+        {
+            var sb = new StringBuilder();
+            sb.Append("Entity=").Append(GetType().Name).Append(";Id=").Append(Id);
+            return sb.ToString();
+        }
+
+        #endregion
+    }
+
+}

+ 14 - 0
Common/qdr.fnd.core.data/Entity/GuidEntity.cs

@@ -0,0 +1,14 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace Quadarax.Foundation.Core.Data.Entity
+{
+    public abstract class GuidEntity : Entity<Guid>
+    {
+        [Key]
+        [Column("Id")]
+        [Required]
+        public override Guid Id { get; set; }
+    }
+}

+ 44 - 0
Common/qdr.fnd.core.data/Entity/NoKey.cs

@@ -0,0 +1,44 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Data.Entity
+{
+    public class NoKey : IEquatable<NoKey>
+    {
+        public Guid Hash { get; }
+
+        public NoKey()
+        {
+            Hash = Guid.NewGuid();
+        }
+
+        public bool Equals(NoKey other)
+        {
+            if (other == null)
+                return false;
+            return Hash == other.Hash;
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != this.GetType()) return false;
+            return Equals((NoKey)obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return Hash.GetHashCode();
+        }
+
+        public static bool operator ==(NoKey left, NoKey right)
+        {
+            return Equals(left, right);
+        }
+
+        public static bool operator !=(NoKey left, NoKey right)
+        {
+            return !Equals(left, right);
+        }
+    }
+}

+ 27 - 0
Common/qdr.fnd.core.data/Extensions/ConnectionStringHelper.cs

@@ -0,0 +1,27 @@
+using System.Data.Common;
+using System.Text;
+
+namespace Quadarax.Foundation.Core.Data.Extensions
+{
+    public class ConnectionStringHelper
+    {
+        private DbConnectionStringBuilder _builder;
+
+        public ConnectionStringHelper(string connectionString)
+        {
+            _builder = new DbConnectionStringBuilder
+            {
+                ConnectionString = connectionString
+            };
+        }
+
+        public override string ToString()
+        {
+            var sb = new StringBuilder();
+            sb.Append(_builder["Database"]);
+            sb.Append("@");
+            sb.Append(_builder["Server"]);
+            return sb.ToString();
+        }
+    }
+}

+ 27 - 0
Common/qdr.fnd.core.data/Extensions/PagingExt.cs

@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Quadarax.Foundation.Core.Data.Extensions
+{
+    public static class PagingExt
+    {
+        public static IQueryable<TEntity> Page<TEntity>(this IQueryable<TEntity> queryable, int? page, int? pageSize, int overlap = 0)
+        {
+            if (!(page.HasValue && pageSize.HasValue))
+                return queryable;
+
+            pageSize = pageSize.GetValueOrDefault(int.MaxValue);
+
+            return queryable.Skip(page.Value * pageSize.Value).Take(pageSize.Value + overlap);
+        }
+
+        public static IEnumerable<TEntity> Page<TEntity>(this IEnumerable<TEntity> queryable, int? page, int? pageSize, int overlap = 0)
+        {
+            if (!(page.HasValue && pageSize.HasValue))
+                return queryable;
+            pageSize = pageSize.GetValueOrDefault(int.MaxValue);
+
+            return queryable.Skip(page.Value * pageSize.Value).Take(pageSize.Value + overlap);
+        }
+    }
+}

+ 19 - 0
Common/qdr.fnd.core.data/Extensions/QueryableExt.cs

@@ -0,0 +1,19 @@
+using System.Linq;
+using Microsoft.EntityFrameworkCore;
+
+namespace Quadarax.Foundation.Core.Data.Extensions
+{
+    public static class QueryableExt
+    {
+        public static IQueryable<TEntity> MultiInclude<TEntity>(this IQueryable<TEntity> queryable, string[] includes) where TEntity : class
+        {
+            if (includes.Length == 0)
+                return queryable;
+
+            foreach (var include in includes)
+                queryable = queryable.Include(include);
+            
+            return queryable;
+        }
+    }
+}

+ 132 - 0
Common/qdr.fnd.core.data/Extensions/SqlConnectionExt.cs

@@ -0,0 +1,132 @@
+using System;
+using System.Data;
+using System.Data.SqlClient;
+
+namespace Quadarax.Foundation.Core.Data.Extensions
+{
+    public static class SqlConnectionExt
+    {
+        public static SqlDataReader Query(this SqlConnection owner, string query, params SqlParameter[] parameters)
+        {
+            if (owner == null)
+                throw new ArgumentNullException(nameof(owner));
+            if (string.IsNullOrEmpty(query))
+                throw new ArgumentNullException(nameof(query));
+
+            var command = owner.CreateCommand();
+            command.CommandText = query;
+            command.CommandType = CommandType.Text;
+
+            if (parameters!=null)
+                foreach (var par in parameters)
+                    command.Parameters.Add(par);
+
+            return command.ExecuteReader(CommandBehavior.Default);
+        }
+
+        public static int Execute(this SqlConnection owner, string query, params SqlParameter[] parameters)
+        {
+            return Execute(owner, CommandType.Text, query, parameters);
+        }
+
+        public static int BatchExecute(this SqlConnection owner, string query, params SqlParameter[] parameters)
+        {
+            var result = 0;
+            var sqlBatch = string.Empty;
+
+            query += "\nGO"; // make sure last batch is executed.
+            foreach (var line in query.Split(new string[] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries))
+            {
+                if (line.ToUpperInvariant().Trim() == "GO")
+                {
+                    if (string.IsNullOrEmpty(sqlBatch)) continue;
+                    result = Execute(owner, sqlBatch, parameters);
+                    sqlBatch = string.Empty;
+                }
+                else
+                {
+                    sqlBatch += line + "\n";
+                }
+            }
+
+            return result;
+        }
+
+        public static int ExecuteSp(this SqlConnection owner, string query, params SqlParameter[] parameters)
+        {
+            return Execute(owner, CommandType.StoredProcedure, query, parameters);
+        }
+
+        public static TResult ExecuteScalar<TResult>(this SqlConnection owner,CommandType type, string query, params SqlParameter[] parameters)
+        {
+            if (owner == null)
+                throw new ArgumentNullException(nameof(owner));
+            if (string.IsNullOrEmpty(query))
+                throw new ArgumentNullException(nameof(query));
+
+            var command = owner.CreateCommand();
+            command.CommandText = query;
+            command.CommandType = type;
+
+            if (parameters!=null)
+                foreach (var par in parameters)
+                    command.Parameters.Add(par);
+
+            return (TResult)command.ExecuteScalar();
+        }
+
+        public static int Execute(this SqlConnection owner, CommandType type, string query,
+            params SqlParameter[] parameters)
+        {
+            if (owner == null)
+                throw new ArgumentNullException(nameof(owner));
+            if (string.IsNullOrEmpty(query))
+                throw new ArgumentNullException(nameof(query));
+
+            var command = new SqlCommand(query, owner);
+            command.CommandType = type;
+
+            if (parameters != null)
+                foreach (var par in parameters)
+                    command.Parameters.Add(par);
+
+            var result = command.ExecuteNonQuery();
+            return result;
+        }
+
+        public static bool DatabasePropertyExists(this SqlConnection owner, string databaseProperty)
+        {
+            return ExecuteScalar<int>(owner, CommandType.Text, $"select count(*) FROM SYS.EXTENDED_PROPERTIES where name='{databaseProperty}' and class_desc = 'DATABASE'") > 0;
+        }
+
+        public static string DatabasePropertyGet(this SqlConnection owner, string databaseProperty)
+        {
+            if (DatabasePropertyExists(owner, databaseProperty))
+                return ExecuteScalar<string>(owner, CommandType.Text, $"select [value] FROM SYS.EXTENDED_PROPERTIES where name='{databaseProperty}' and class_desc = 'DATABASE'");
+            else
+                return string.Empty;
+        }
+
+        public static bool DatabasePropertyAddOrUpdate(this SqlConnection owner, string databaseProperty, string value)
+        {
+            bool result;
+            var spParams = new SqlParameter[]
+            {
+                new SqlParameter("@name", SqlDbType.VarChar) { Value = databaseProperty },
+                new SqlParameter("@value", SqlDbType.VarChar) { Value = value },
+            };
+
+            if (DatabasePropertyExists(owner, databaseProperty))
+            {
+                result = ExecuteSp(owner, "sys.sp_updateextendedproperty", spParams) > 0;
+            }
+            else
+            {
+                result = ExecuteSp(owner, "sys.sp_addextendedproperty", spParams) > 0;
+            }
+
+            return result;
+        }
+
+    }
+}

+ 82 - 0
Common/qdr.fnd.core.data/Mapper/Mapper.cs

@@ -0,0 +1,82 @@
+using System;
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+using Quadarax.Foundation.Core.Mapper;
+
+namespace Quadarax.Foundation.Core.Data.Mapper
+{
+    public class Mapper<TMapper> : Loom where TMapper : class, new()
+    {
+        /// <summary>
+        /// Singleton instance of this class.
+        /// </summary>
+        public static TMapper Instance => _instance.Value;
+
+        private static readonly Lazy<TMapper> _instance = new Lazy<TMapper>(() => new TMapper());
+
+        #region ------ Constructors ---------------------------------------------------------------
+
+        /// <summary>
+        /// Initializes a new instance of this class.
+        /// </summary>
+        public Mapper()
+        {
+            
+        }
+
+        /// <summary>
+        /// Defines mappings from a DAO to DTO and vice-versa.
+        /// </summary>
+        /// <typeparam name="TDao"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        protected void DefineBiDirection<TDao, TDto, TKey>() 
+            where TDao : class, IDao<TKey>, new()
+            where TDto : class, IDto, new()
+            where TKey : IEquatable<TKey>
+        {
+            Define<TDao, TDto>()
+                .PublicProperties()
+                .Compile();
+            Define<TDto, TDao>()
+                .PublicProperties()
+                .Compile();
+        }
+
+        protected void Define<TDao, TDto>(Action<LoomBuilder<TDao, TDto>> customFromDao)
+            where TDao : class, IDao<long>, new()
+            where TDto : class, IDto, new()
+        {
+            // from DAO to DTo
+            var builder = Define<TDao, TDto>();
+            builder.PublicProperties();
+            customFromDao?.Invoke(builder);
+            builder.Compile();
+
+        }
+
+        protected void DefineReverse<TDto, TDao>(Action<LoomBuilder<TDto, TDao>> customFromDao)
+            where TDao : class, IDao<long>, new()
+            where TDto : class, IDto, new()
+        {
+            // from DTO to DAO
+            var builder = Define<TDto, TDao>();
+            builder.PublicProperties();
+            customFromDao?.Invoke(builder);
+            builder.Compile();
+
+        }
+
+        protected void DefineReverse<TDto, TDao>()
+            where TDao : class, IDao<long>, new()
+            where TDto : class, IDto, new()
+        {
+            // from DTO to DAO
+            var builder = Define<TDto, TDao>();
+            builder.PublicProperties();
+            builder.Compile();
+
+        }
+
+
+        #endregion
+    }
+}

+ 57 - 0
Common/qdr.fnd.core.data/Mapper/MapperExt.cs

@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+
+namespace Quadarax.Foundation.Core.Data.Mapper
+{
+    /*
+    public static class MapperExt
+    {
+        public static TDto Map<TDao, TDto, TKey>(this TDao dao)
+            where TDao : class, IDao<TKey>, new()
+            where TDto : class, IDto, new()
+            where TKey : IEquatable<TKey>
+        {
+            if (dao == null) return null;
+            return Mapper.Instance.Map<TDao, TDto>(dao);
+        }
+
+        public static TDao MapDto<TDto, TDao, TKey>(this TDto dto)
+            where TDao : class, IDao<TKey>, new()
+            where TDto : class, IDto, new()
+            where TKey : IEquatable<TKey>
+        {
+            if (dto == null) return null;
+            return Mapper.Instance.Map<TDto, TDao>(dto);
+        }
+
+        public static List<TDto> MapList<TDao, TDto, TKey>(this IQueryable<TDao> dao)
+            where TDao : class, IDao<TKey>, new()
+            where TDto : class, IDto, new()
+            where TKey : IEquatable<TKey>
+        {
+            if (dao == null) return new List<TDto>();
+            return Mapper.Instance.MapList<TDao, TDto>(dao);
+        }
+
+        public static List<TDto> MapList<TDao, TDto,TKey>(this IEnumerable<TDao> dao)
+            where TDao : class, IDao<TKey>, new()
+            where TDto : class, IDto, new()
+            where TKey : IEquatable<TKey>
+        {
+            if (dao == null) return new List<TDto>();
+            return Mapper.Instance.MapList<TDao, TDto>(dao);
+        }
+
+        public static IQueryable<TDao> MapListDto<TDto,TDao,TKey>(this IEnumerable<TDto> dto)
+            where TDao : class, IDao<TKey>, new()
+            where TDto : class, IDto, new()
+            where TKey : IEquatable<TKey>
+        {
+            if (dto == null) return new List<TDao>().AsQueryable();
+            return Mapper.Instance.MapList<TDto, TDao>(dto.AsQueryable()).AsQueryable();
+        }
+    }
+    */
+}

+ 15 - 0
Common/qdr.fnd.core.data/Mapper/MapperGuid.cs

@@ -0,0 +1,15 @@
+using System;
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+
+namespace Quadarax.Foundation.Core.Data.Mapper
+{
+    public class MapperGuid : Mapper<MapperGuid>
+    {
+        public void DefineBiDirection<TDao, TDto>() 
+            where TDao : class, IDao<Guid>, new()
+            where TDto : class, IDto, new()
+        {
+            DefineBiDirection<TDao, TDto, Guid>();
+        }
+    }
+}

+ 70 - 0
Common/qdr.fnd.core.data/Mapper/MapperGuidExt.cs

@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+
+namespace Quadarax.Foundation.Core.Data.Mapper
+{
+    public static class MapperGuidExt
+    {
+        public static TDto Map<TDao, TDto>(this TDao dao)
+            where TDao : class, IDao<Guid>, new()
+            where TDto : class, IDto, new()
+        {
+            if (dao == null) return null;
+            return Mapper<MapperGuid>.Instance.Map<TDao, TDto>(dao);
+        }
+
+        public static TDao MapDto<TDto, TDao>(this TDto dto)
+            where TDao : class, IDao<Guid>, new()
+            where TDto : class, IDto, new()
+        {
+            if (dto == null) return null;
+            return Mapper<MapperGuid>.Instance.Map<TDto, TDao>(dto);
+        }
+
+        public static void CopyToDto<TDto, TDao>(this TDto @from, TDao to)
+            where TDao : class, IDao<Guid>, new()
+            where TDto : class, IDto, new()
+        {
+            if (@from == null) return;
+            if (to == null) return;
+            Mapper<MapperGuid>.Instance.Update(@from,to);
+        }
+
+        public static void CopyToDto<TDto, TDao>(this TDao @from, TDto to)
+            where TDao : class, IDao<Guid>, new()
+            where TDto : class, IDto, new()
+        {
+            if (to == null) return;
+            if (@from == null) return;
+            Mapper<MapperGuid>.Instance.Update(@from,to);
+        }
+
+
+        public static List<TDto> MapList<TDao, TDto>(this IQueryable<TDao> dao)
+            where TDao : class, IDao<Guid>, new()
+            where TDto : class, IDto, new()
+        {
+            if (dao == null) return new List<TDto>();
+            return Mapper<MapperGuid>.Instance.MapList<TDao, TDto>(dao);
+        }
+
+        public static List<TDto> MapList<TDao, TDto>(this IEnumerable<TDao> dao)
+            where TDao : class, IDao<Guid>, new()
+            where TDto : class, IDto, new()
+        {
+            if (dao == null) return new List<TDto>();
+            return Mapper<MapperGuid>.Instance.MapList<TDao, TDto>(dao);
+        }
+
+        public static IQueryable<TDao> MapListDto<TDto,TDao>(this IEnumerable<TDto> dto)
+            where TDao : class, IDao<Guid>, new()
+            where TDto : class, IDto, new()
+        {
+            if (dto == null) return new List<TDao>().AsQueryable();
+            return Mapper<MapperGuid>.Instance.MapList<TDto, TDao>(dto.AsQueryable()).AsQueryable();
+        }
+
+    }
+}

+ 50 - 0
Common/qdr.fnd.core.data/Paging.cs

@@ -0,0 +1,50 @@
+using System;
+using Quadarax.Foundation.Core.Data.Interface;
+
+namespace Quadarax.Foundation.Core.Data
+{
+    public class Paging : IPaging
+    {
+        #region *** Properties ***
+        /// <summary>
+        /// Zero based index
+        /// </summary>
+        public int Page { get; }
+        /// <summary>
+        /// Number of items per page
+        /// </summary>
+        public int PageSize { get; }
+        /// <summary>
+        /// Defines if paging is disabled
+        /// </summary>
+        public bool IsDisabled { get;  }
+        #endregion
+
+        #region *** Constructors ***
+        public Paging(int page, int pageSize)
+        {
+            IsDisabled = pageSize == 0;
+
+            Page = page;
+            PageSize = pageSize;
+        }
+
+        public Paging()
+        {
+            IsDisabled = true;
+        }
+
+        public static Paging NoPaging()
+        {
+            return new Paging();
+        }
+        #endregion
+
+        #region *** Overrides ***
+        public override string ToString()
+        {
+            return $"Paging:IsDisabled={IsDisabled};Page={Page};PageSize={PageSize}";
+        }
+        #endregion
+    }
+}

+ 96 - 0
Common/qdr.fnd.core.data/Repository/EntityRepository.cs

@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Microsoft.EntityFrameworkCore;
+using Quadarax.Foundation.Core.Data.Domain;
+using Quadarax.Foundation.Core.Data.Entity;
+using Quadarax.Foundation.Core.Data.Extensions;
+using Quadarax.Foundation.Core.Data.Interface;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+using Quadarax.Foundation.Core.Data.Interface.Repository;
+
+namespace Quadarax.Foundation.Core.Data.Repository
+{
+    public abstract class EntityRepository<TKey, TEntity> : IDaoRepository<TKey, TEntity> 
+        where TEntity : Entity<TKey>, new() 
+        where TKey : IEquatable<TKey>
+    {
+        private IUnitOfWork<DataDomain> _unitOfWork;
+        private DbSet<TEntity> DbSetInstance => _unitOfWork.Context.GetDbSet<DbSet<TEntity>>();
+        protected DataDomain Context => _unitOfWork.Context;
+        
+        protected IList<string> DefaultIncludes { get; }
+
+        protected EntityRepository(IUnitOfWork<DataDomain> unitOfWork)
+        {
+            _unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
+            DefaultIncludes = new List<string>();
+            //_dbSet = domain.GetDbSet<DbSet<TEntity>>();
+        }
+
+        public virtual IQueryable<TEntity> Query(IPaging paging,bool usingUncommited=false)
+        {
+            var local = DbSetInstance.Local.Page(paging.IsDisabled ? (int?) null : paging.Page, paging.PageSize).AsQueryable();
+            if (local.Any() && usingUncommited)
+            {
+                return local.MultiInclude(DefaultIncludes.ToArray());
+            }
+
+            return DbSetInstance.Page(paging.IsDisabled ? (int?) null : paging.Page, paging.PageSize).MultiInclude(DefaultIncludes.ToArray());
+        }
+
+        public virtual TEntity Get(TKey id)
+        {
+            return Query(new Paging()).MultiInclude(DefaultIncludes.ToArray()).FirstOrDefault(x => Equals(x.Id, id));
+        }
+
+        public virtual IQueryable<TEntity> Get(IEnumerable<TKey> ids)
+        {
+            return Query(new Paging()).Where(x => ids.Contains(x.Id));
+        }
+
+        public virtual TEntity Set(TEntity entity)
+        {
+            //DbSetInstance.Update(entity);
+            return entity;
+        }
+
+        public virtual IEnumerable<TEntity> Set(IEnumerable<TEntity> entities)
+        {
+            return entities.Select(Set).ToList();
+        }
+
+        public virtual TEntity New()
+        {
+            return DbSetInstance.Add(new TEntity()).Entity;
+        }
+
+        public virtual bool Remove(TKey id)
+        {
+            DbSetInstance.Remove(Get(id));
+            return true;
+        }
+
+        public virtual IEnumerable<bool> Remove(IEnumerable<TKey> ids)
+        {
+            return ids.Select(Remove).ToList();
+        }
+
+        public virtual bool Remove(TEntity entity)
+        {
+            DbSetInstance.Remove(entity);
+            return true;
+        }
+
+        public virtual IEnumerable<bool> Remove(IEnumerable<TEntity> entities)
+        {
+            return entities.Select(Remove).ToList();
+        }
+
+        public void Commit()
+        {
+            _unitOfWork.Commit();
+        }
+    }
+}

+ 22 - 0
Common/qdr.fnd.core.data/qdr.fnd.core.data.csproj

@@ -0,0 +1,22 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>..\bo_strong_key_pair.snk</AssemblyOriginatorKeyFile>
+    <DelaySign>false</DelaySign>
+    <RootNamespace>Quadarax.Foundation.Core.Data</RootNamespace>
+    <ApplicationIcon>..\quadarax_dll.ico</ApplicationIcon>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.9" />
+    <PackageReference Include="System.Data.SqlClient" Version="4.8.3" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\qdr.fnd.core.data.itfc\qdr.fnd.core.data.itfc.csproj" />
+    <ProjectReference Include="..\qdr.fnd.core\qdr.fnd.core.csproj" />
+  </ItemGroup>
+
+</Project>

+ 30 - 0
Common/qdr.fnd.core.nlog/LogSeverityEnumExt.cs

@@ -0,0 +1,30 @@
+using System;
+using NLog;
+using Quadarax.Foundation.Core.Logging;
+
+namespace Quadarax.Foundation.Core.NLog
+{
+    public static class LogSeverityEnumExt
+    {
+        public static LogLevel ToNLogLevel(this LogSeverityEnum owner)
+        {
+            switch (owner)
+            {
+                    case LogSeverityEnum.Trace:
+                        return LogLevel.Trace;
+                    case LogSeverityEnum.Debug:
+                        return LogLevel.Debug;
+                    case LogSeverityEnum.Info:
+                        return LogLevel.Info;
+                    case LogSeverityEnum.Warn:
+                        return LogLevel.Warn;
+                    case LogSeverityEnum.Error:
+                        return LogLevel.Error;
+                    case LogSeverityEnum.Fatal:
+                        return LogLevel.Fatal;
+                    default:
+                        throw new NotSupportedException($"Not supported enum conversion for '{owner}'");
+            }
+        }
+    }
+}

+ 43 - 0
Common/qdr.fnd.core.nlog/Logger.cs

@@ -0,0 +1,43 @@
+using System;
+using NLog;
+using Quadarax.Foundation.Core.Logging;
+
+namespace Quadarax.Foundation.Core.NLog
+{
+    public class Logger : ILog
+    {
+
+        private global::NLog.ILogger _logger;
+        public string Name { get; }
+
+
+        public Logger(Type type) : this(type.Name)
+        {
+        }
+        public Logger(string name)
+        {
+            Name = name;
+            _logger = LogManager.GetLogger(name);
+        }
+
+        public void Log(LogSeverityEnum severity, int code, string message)
+        {
+            _logger.Log(severity.ToNLogLevel(), message, code);
+        }
+
+        public void Log(LogSeverityEnum severity, string message)
+        {
+            _logger.Log(severity.ToNLogLevel(), message);
+        }
+
+        public void Log(LogSeverityEnum severity, string message, Exception exception)
+        {
+            _logger.Log(severity.ToNLogLevel(), exception, message);
+        }
+
+        public void Log(LogSeverityEnum severity, int code, string message, Exception exception)
+        {
+            _logger.Log(severity.ToNLogLevel(), exception, message, code);
+        }
+    }
+}

+ 45 - 0
Common/qdr.fnd.core.nlog/LoggerFactory.cs

@@ -0,0 +1,45 @@
+using System;
+using NLog;
+using NLog.Config;
+using Quadarax.Foundation.Core.Logging;
+using Quadarax.Foundation.Core.Object;
+using ILogger = Quadarax.Foundation.Core.Logging.ILogger;
+
+namespace Quadarax.Foundation.Core.NLog
+{
+    public class LoggerFactory : Singleton<ILogger, LoggerFactory>, ILogger
+    {
+
+        public static string ConfigurationFileName { get; set; }
+
+        public void Configure(string configurationFileName)
+        {
+
+            if (!string.IsNullOrEmpty(configurationFileName))
+            {
+                LogManager.Configuration = new XmlLoggingConfiguration(configurationFileName);
+                var log = Instance.GetLogger(GetType());
+                log.Log(LogSeverityEnum.Debug, $"NLOG initialized from configuration file '{configurationFileName}'");
+            }
+        }
+
+        public ILog GetLogger(string loggerName)
+        {
+            return Instance.GetLogger(loggerName);
+        }
+
+        public ILog GetLogger(Type loggerForType)
+        {
+            return Instance.GetLogger(loggerForType);
+        }
+
+        ILog ILogger.GetLogger(string loggerName)
+        {
+            return new Logger(loggerName);
+        }
+        ILog ILogger.GetLogger(Type loggerForType)
+        {
+            return new Logger(loggerForType);
+        }
+    }
+}

+ 21 - 0
Common/qdr.fnd.core.nlog/qdr.fnd.core.nlog.csproj

@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>..\bo_strong_key_pair.snk</AssemblyOriginatorKeyFile>
+    <DelaySign>false</DelaySign>
+    <RootNamespace>Quadarax.Foundation.Core.NLog</RootNamespace>
+    <ApplicationIcon>..\quadarax_dll.ico</ApplicationIcon>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="NLog" Version="5.0.4" />
+    <PackageReference Include="NLog.Extensions.Logging" Version="5.0.4" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\qdr.fnd.core\qdr.fnd.core.csproj" />
+  </ItemGroup>
+
+</Project>

+ 90 - 0
Common/qdr.fnd.core.qconsole/Argument/AbstractArgument.cs

@@ -0,0 +1,90 @@
+using System;
+using System.Text;
+using Quadarax.Foundation.Core.QConsole.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Argument
+{
+    public abstract class AbstractArgument
+    {
+        #region *** Properties ***
+        /// <summary>
+        /// Defines access code to argument
+        /// <example>
+        /// c, a, file, path, ...
+        /// </example>
+        /// </summary>
+        public string Code { get; }
+
+        /// <summary>
+        /// Defines name of value in short displaying form
+        /// <example>
+        /// file_name, name_of_database, number, ...
+        /// </example>
+        /// </summary>
+        public string Hint { get; }
+
+        /// <summary>
+        /// Full description for argument
+        /// </summary>
+        public string Description { get; }
+
+        /// <summary>
+        /// Defines if argument is mandatory. If True, then if argument is not specified, then error occures.
+        /// </summary>
+        public bool IsMandatory { get; }
+
+        /// <summary>
+        /// Current value of argument
+        /// </summary>
+        public AbstractValue Value { get; }
+
+        /// <summary>
+        /// Default value of argument, uses if argument is not specified.
+        /// </summary>
+        public AbstractValue DefaultValue { get; }
+
+
+
+        public bool WasUsed { get; private set; }
+        #endregion
+
+        #region *** Constructors ***
+        #endregion
+
+        #region *** Public operations ***
+
+        public AbstractArgument(string code, string description, string hint, TypeValuesEnum valueType, string defaultValue, bool isMandatory)
+        {
+            if (string.IsNullOrEmpty(code))
+                throw new ArgumentNullException();
+            Code = code;
+            Description = description;
+            Hint = hint;
+            IsMandatory = isMandatory;
+
+            Value = AbstractValue.Create(valueType);
+            DefaultValue = AbstractValue.Create(valueType);
+
+            DefaultValue.Set(defaultValue);
+        }
+        #endregion
+
+        public void SetValueAsDefault()
+        {
+            if (DefaultValue.HasValue)
+                Value.Set(DefaultValue.Get());
+        }
+
+        public void Hit()
+        {
+            WasUsed = true;
+        }
+
+        public override string ToString()
+        {
+            var sb = new StringBuilder();
+            sb.Append("[").Append(Code).Append("] ").Append(Hint);
+            return sb.ToString();
+        }
+    }
+}

+ 23 - 0
Common/qdr.fnd.core.qconsole/Argument/FlagArgument.cs

@@ -0,0 +1,23 @@
+using Quadarax.Foundation.Core.QConsole.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Argument
+{
+    public class FlagArgument : NamedArgument
+    {
+        public FlagArgument(string code, string description, string hint, bool defaultValue) : base(code, description, hint, TypeValuesEnum.Bool, defaultValue.ToString(), false)
+        {
+            Reset();
+        }
+
+        public void Set()
+        {
+            Value.Set(!(bool)DefaultValue.Get());
+            Hit();
+        }
+
+        public void Reset()
+        {
+            Value.Set(DefaultValue.Get());
+        }
+    }
+}

+ 11 - 0
Common/qdr.fnd.core.qconsole/Argument/NamedArgument.cs

@@ -0,0 +1,11 @@
+using Quadarax.Foundation.Core.QConsole.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Argument
+{
+    public class NamedArgument : AbstractArgument
+    {
+        public NamedArgument(string code, string description, string hint, TypeValuesEnum valueType, string defaultValue, bool isMandatory) : base(code, description, hint, valueType, defaultValue, isMandatory)
+        {
+        }
+    }
+}

+ 23 - 0
Common/qdr.fnd.core.qconsole/Argument/OrdinalArgument.cs

@@ -0,0 +1,23 @@
+using Quadarax.Foundation.Core.QConsole.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Argument
+{
+    public class OrdinalArgument : AbstractArgument
+    {
+        /// <summary>
+        /// Defines if ordinal argument can be also used as named argument.
+        /// </summary>
+        public bool IsCodeAllowed { get; }
+
+        /// <summary>
+        /// Ordinal position in command line from left.
+        /// </summary>
+        public int OrdinalNumber { get; }
+
+        public OrdinalArgument(int ordinalNumber,  bool isCodeAllowed, string code, string description, string hint, TypeValuesEnum valueType, string defaultValue, bool isMandatory) : base(code, description, hint, valueType, defaultValue, isMandatory)
+        {
+            OrdinalNumber = ordinalNumber;
+            IsCodeAllowed = isCodeAllowed;
+        }
+    }
+}

+ 9 - 0
Common/qdr.fnd.core.qconsole/Attributes/CommandDefinitionAttribute.cs

@@ -0,0 +1,9 @@
+using System;
+
+namespace Quadarax.Foundation.Core.QConsole.Attributes
+{
+    [AttributeUsage(AttributeTargets.Class)]
+    public class CommandDefinitionAttribute : Attribute
+    {
+    }
+}

+ 393 - 0
Common/qdr.fnd.core.qconsole/Command/Base/AbstractCommand.cs

@@ -0,0 +1,393 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.QConsole.Argument;
+using Quadarax.Foundation.Core.QConsole.Context;
+using Quadarax.Foundation.Core.QConsole.Extensions;
+using Quadarax.Foundation.Core.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Command.Base
+{
+    public abstract class AbstractCommand
+    {
+        #region *** Enumerations ***
+
+        public enum WriteTextSeverity
+        {
+            Info,
+            Caption,
+            Warning,
+            Error,
+        }
+        #endregion
+
+        #region *** Private Fields ***
+        private Engine _engine;
+        private IDictionary<string, AbstractArgument> _arguments;
+        protected ICommandContext _context;
+        #endregion
+
+        #region *** Properties ***
+        public abstract string Name { get; }
+        public abstract string Description { get; }
+        public virtual string Notes { get; set; }
+        public virtual string Examples { get; set; }
+        public virtual string CustomUsage { get; set; }
+        public AbstractArgument[] Arguments => _arguments.Values.ToArray();
+
+        protected Engine Engine => _engine;
+        #endregion
+
+        #region  *** Constructor ***
+
+        public AbstractCommand(Engine engine)
+        {
+            _engine = engine ?? throw new ArgumentNullException(nameof(engine));
+            _arguments = new Dictionary<string, AbstractArgument>();
+            _context = _engine.Context.CreateCommandContext();
+            WriteDebugInfo($"Context for command '{Name}' created: {_context}");
+            var args = SetupArguments();
+            foreach (var arg in args)
+                _arguments.Add(arg.Code, arg);
+
+            Init();
+
+            WriteDebugInfo($"Command '{Name}' has {_arguments.Count} arguments. Initialized.");
+        }
+        #endregion
+
+        #region *** Public operations ***
+        public Result Execute(string input)
+        {
+            ConsoleWriter writer = null;
+            try
+            {
+                writer = new ConsoleWriter(ConsoleColor.Green);
+                foreach (var arg in Arguments)
+                    arg.SetValueAsDefault();
+                ParseInput(input);
+                OnInitialize();
+                if (_engine.Configuration.ShowStatusOnEveryCommand)
+                    ShowContextStatus(writer);
+                OnValidateArguments();
+                BeginExecute();
+                var result = OnExecute();
+                result = EndExecute(result);
+                return result;
+            }
+            catch (Exception e)
+            {
+                return new Result(e);
+            }
+            finally
+            {
+                writer?.Dispose();
+            }
+        }
+
+
+        public override string ToString()
+        {
+            return "Command: " + Name;
+        }
+        #endregion
+
+        #region *** Private operations ***
+
+        private void Init()
+        {
+            OnCommandInit();
+        }
+        private void ParseInput(string input)
+        {
+            //var args = input.Split(new[] {Engine.Configuration.CharacterNamedArgumentSeparator}, StringSplitOptions.RemoveEmptyEntries);
+            var args = Split(input, Engine.Configuration.CharacterTextValueBraceSeparator, new[]
+            {
+                Engine.Configuration.CharacterNamedArgumentSeparator,
+                Engine.Configuration.CharacterOrdinalArgumentSeparator
+            });
+
+
+            for (int i = 1; i < args.Length; i++)
+            {
+                var arg = args[i];
+                var index = i - 1;
+                WriteDebugInfo($"Parsing argument [index={index}] by value string '{arg}' in progress..");
+                AbstractArgument argument = null;
+                if (arg.StartsWith(Engine.Configuration.CharacterNamedArgumentSeparator))
+                {
+                    //Named
+                    WriteDebugInfo("Detects argument as named.");
+                    var parsed = ParseNamedArgument(arg);
+                    if (!ContainsArgument(parsed.Item1))
+                        throw new Exception(
+                            $"Invalid argument '{Engine.Configuration.CharacterNamedArgumentSeparator}{parsed.Item1}' for this command.");
+                    argument = GetArgument(parsed.Item1);
+                    if (argument.IsPositional())
+                        if (!((OrdinalArgument)argument).IsCodeAllowed)
+                            throw new Exception($"Usage of ordinal argument '{argument.Code}' as named argument is not allowed!");
+                    if (argument.IsFlag())
+                        ((FlagArgument)argument).Set();
+                    else
+                    {
+                        argument.Value.Set(parsed.Item2);
+                        argument.Hit();
+                    }
+                }
+                else
+                {
+                    //Ordinal
+                    WriteDebugInfo("Detects argument as ordinal.");
+                    argument = GetArgument(index);
+                    if (argument == null)
+                        throw new Exception(
+                            $"Invalid ordinal argument '{arg}' at position {index} for this command.");
+
+                    argument.Value.Set(arg);
+                    argument.Hit();
+                    WriteDebugInfo($"Ordinal argument '{argument.Code}' is set to value '{argument.Value.AsString()}'.");
+                }
+            }
+        }
+
+        private Tuple<string, string> ParseNamedArgument(string argument)
+        {
+            try
+            {
+                var argParts = argument.Split(new[] {Engine.Configuration.CharacterNamedArgumentValueSeparator}, StringSplitOptions.RemoveEmptyEntries);
+                WriteDebugInfo($"Splitting arg-parts '{argument}' to parts (count={argParts.Length}): {string.Join(",",argParts)}");
+                var argName = argParts[0].Replace(Engine.Configuration.CharacterNamedArgumentSeparator,string.Empty);
+                var argValue = argParts.Length > 1 ? string.Join(Engine.Configuration.CharacterNamedArgumentValueSeparator,argParts.Skip(1).Take(argParts.Length - 1)).Replace(_engine.Configuration.CharacterTextValueBraceSeparator,string.Empty) : string.Empty;
+                WriteDebugInfo($"Named argument '{argument}' parsed as name='{argName}'; value='{argValue}'.");
+                return new Tuple<string, string>(argName, argValue);
+            }
+            catch (Exception e)
+            {
+                WriteDebugInfo($"Error during parsing named argument '{argument}'.");
+                throw new Exception($"Argument '{argument}' parsing error.", e);
+            }
+            
+        }
+        private string[] Split(string input, string valueBracket, string[] separators)
+        {
+            var result = new List<string>();
+            var trimedInput = input.Trim();
+            if (string.IsNullOrEmpty(trimedInput))
+                return result.ToArray();
+
+            var cValueBracked = valueBracket.ToCharArray().First();
+            var cSeparators = separators.Select(x => x.ToCharArray().First());
+
+            var nIndexStart = 0;
+            var nIndexEnd = 0;
+            var isInsideBracked = false;
+            int offset = 0;
+
+            for (offset = 0; offset < trimedInput.Length; offset++)
+            {
+                var current = trimedInput[offset];
+                // current | isInside | Result
+                //   1          1          0
+                //   1          0          1
+                //   0          1          1
+                //   0          0          0
+                isInsideBracked = current == cValueBracked ^ isInsideBracked;
+                if (isInsideBracked)
+                    continue;
+                if (cSeparators.Contains(current))
+                {
+                    nIndexEnd = offset;
+                    result.Add(trimedInput.Substring(nIndexStart,nIndexEnd - nIndexStart));
+                    nIndexStart = nIndexEnd;
+                    isInsideBracked = false;
+                }
+            }
+
+            if (offset>nIndexStart)
+                result.Add(trimedInput.Substring(nIndexStart,offset - nIndexStart));
+
+            return result.Where(x => !string.IsNullOrEmpty(x.Trim())).Select(x=>x.Trim()).ToArray();
+        }
+        private IEnumerable<AbstractArgument> SetupArguments()
+        {
+            return OnSetupArguments();
+        }
+        protected void WriteDebugInfo(string text)
+        {
+            using (var debug = new DebugConsoleWriter())
+            {
+                debug.WriteDebugLine(text);
+            }
+        }
+
+        protected void WriteInfo(string text)
+        {
+            using (var writer = new ConsoleWriter(ConsoleColor.Green))
+                WriteLine(writer,WriteTextSeverity.Info, text);
+        }
+
+        protected void WriteCaption(string text)
+        {
+            using (var writer = new ConsoleWriter(ConsoleColor.White))
+                WriteLine(writer,WriteTextSeverity.Caption, text);
+        }
+
+        protected void WriteWarning(string text)
+        {
+            using (var writer = new ConsoleWriter(ConsoleColor.Yellow))
+                WriteLine(writer,WriteTextSeverity.Warning, text);
+        }
+
+        protected void WriteError(string text)
+        {
+            using (var writer = new ConsoleWriter(ConsoleColor.Red))
+                WriteLine(writer, WriteTextSeverity.Error, text);
+        }
+
+        protected void WriteError(Exception e)
+        {
+            if (e is AggregateException aggr)
+            {
+                foreach (var ex in aggr.InnerExceptions)
+                    DumpException(ex, "- ");
+            }
+            else
+                DumpException(e, string.Empty);
+        }
+
+        private void DumpException(Exception e, string prefix)
+        {
+            while (e != null)
+            {                                         
+                WriteError(prefix + e.Message);
+                e = e.InnerException;
+            }
+        }
+
+        protected virtual void WriteLine(ConsoleWriter writer, WriteTextSeverity severity, string text)
+        {
+            writer.WriteLine(text);
+        }
+        
+        private void ShowContextStatus(ConsoleWriter writer)
+        {
+            using (var writerBlue = new ConsoleWriter(ConsoleColor.Blue))
+            {
+                using (var writerYellow = new ConsoleWriter(ConsoleColor.Magenta))
+                {
+                    writer.WriteLine("Engine context:");
+                    writerBlue.Write(_engine.Context.ToString()).Write(" : ");
+                    writerYellow.WriteLine(_engine.Context.Status);
+                    writer.WriteLine("Command context:");
+                    writerBlue.Write(_context.ToString()).Write(" : ");
+                    writerYellow.WriteLine(_context.Status);
+                }
+            }
+        }
+
+        #endregion
+
+        #region *** Protected virtuals ***
+        protected virtual void OnCommandInit()
+        {
+            WriteDebugInfo("Command called OnCommandInit.");
+        }
+        protected virtual IEnumerable<AbstractArgument> OnSetupArguments()
+        {
+            return new AbstractArgument[0];
+            //{
+            //    new FlagArgument(Constants.Arguments.General.DebugMode.Code, Constants.Arguments.General.DebugMode.Description, Constants.Arguments.General.DebugMode.Hint, true), 
+            //};
+        }
+
+        
+        protected abstract Result OnExecute();
+
+        protected virtual void OnValidateArguments()
+        {
+            var ex = new List<Exception>();
+            foreach (var arg in _arguments.Where(x=>x.Value.IsMandatory).Select(x=>x.Value))
+            {
+                if (!arg.Value.HasValue)
+                    ex.Add(new Exception($"Argument '{arg.Code}' is mandatory!"));
+            }
+
+            if (ex.Count > 0)
+                throw new AggregateException(ex);
+        }
+
+        protected virtual void OnInitialize()
+        {
+        }
+
+        protected virtual void BeginExecute()
+        {
+        }
+
+        protected virtual Result EndExecute(Result incommingResult)
+        {
+            return incommingResult;
+        }
+        #endregion
+
+        #region *** Protected operations ***
+        protected AbstractArgument GetArgument(string code)
+        {
+            if (!_arguments.ContainsKey(code)) 
+                throw new Exception($"Argument '{code}' is not defined.");
+            return _arguments[code];
+        }
+        protected AbstractArgument GetArgument(int ordinalPosition)
+        {
+            return _arguments.Values.Where(x => x.IsPositional()).Skip(ordinalPosition).FirstOrDefault();
+        }
+
+        protected TValue GetArgumentValueOrDefault<TValue>(string code, TValue defalutValue)
+        {
+            if (!ContainsArgument(code)) return defalutValue;
+            return (TValue) GetArgumentValueOrDefault<TValue>(code);
+        }
+        protected TValue GetArgumentValueOrDefault<TValue>(string code)
+        {
+            if (!ContainsArgument(code)) throw new ArgumentOutOfRangeException(code, $"Argument '{code}' not defined.");
+            var arg = GetArgument(code);
+            var value = arg.Value.Get() ?? arg.DefaultValue.Get();
+            if (typeof(TValue).IsEnum)
+                return (TValue)Enum.Parse(typeof(TValue), value?.ToString(),true);
+            return (TValue) value;
+        }
+
+        protected bool WasArgumentSpecified(string code)
+        {
+            if (!ContainsArgument(code)) throw new ArgumentOutOfRangeException(code, $"Argument '{code}' not defined.");
+            var arg = GetArgument(code);
+            return arg.Value.HasValue && arg.WasUsed;
+        }
+
+        protected void ValidateArgumentValueEnum(string argumentName, Type enumType)
+        {
+            var argVal = GetArgumentValueOrDefault<string>(argumentName);
+            if (!Enum.GetNames(enumType).Select(x => x.ToLower()).Contains(argVal.ToLower()))
+                throw new ArgumentOutOfRangeException(
+                    $"Argument '{argumentName}' value must be set as following: {string.Join(",", Enum.GetNames(enumType))}");
+
+        }
+        protected void ValidateArgumentValueEnum<TEnum>(string argumentName) where TEnum : Enum
+        {
+            ValidateArgumentValueEnum(argumentName, typeof(TEnum));
+        }
+        protected bool ContainsArgument(string code)
+        {
+            return _arguments.ContainsKey(code);
+        }
+
+        protected TContext GetContext<TContext>() where TContext : class, ICommandContext
+        {
+            return (TContext)_context;
+        }
+        #endregion
+
+    }
+}

+ 270 - 0
Common/qdr.fnd.core.qconsole/Command/Base/AbstractListCommand.cs

@@ -0,0 +1,270 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.QConsole.Argument;
+using Quadarax.Foundation.Core.QConsole.Value;
+using Quadarax.Foundation.Core.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Command.Base
+{
+    public abstract class AbstractListCommand : AbstractCommand
+    {
+        #region *** Private Fields ***
+        private readonly IList<ISelectionEntry> _items = new List<ISelectionEntry>();
+        #endregion
+
+        #region *** Properties ***
+        protected IEnumerable<ISelectionEntry> Items => _items;
+        #endregion
+
+        #region *** Constructors ***
+        protected AbstractListCommand(Engine engine) : base(engine)
+        {
+           
+        }
+        #endregion
+
+        #region *** Public Operations ***
+        public void SetModel(ISelectionEntry[] modelItems, bool isItemAppends = false)
+        {
+            if (modelItems == null)
+                throw new ArgumentNullException(nameof(modelItems));
+            if (!isItemAppends)
+                ClearModel();
+            foreach (var item in modelItems)
+                _items.Add(item);
+            var asAppend = isItemAppends ? "as appended" : "";
+            WriteDebugInfo($"Command '{Name}' model set {asAppend} with {_items.Count} items.");
+        }
+
+        public void ClearModel()
+        {
+            _items.Clear();
+            WriteDebugInfo($"Command '{Name}' model was clear.");
+        }
+
+        public ISelectionEntry GetItem(int ordinal)
+        {
+            return _items[ordinal];
+        }
+        #endregion
+
+        #region *** Protected overrides ***
+        protected override Result EndExecute(Result incommingResult)
+        {
+            
+            if (_items == null)
+                throw new Exception($"Command '{Name}' must have set model first in OnExecute.");
+            
+            using (var writer = new ConsoleWriter(ConsoleColor.Yellow))
+            {
+                using (var writerGreen = new ConsoleWriter(ConsoleColor.Green))
+                {
+                    SetupPaging();
+                    var isEndOfPaging = false;
+                    
+                    writerGreen.Write("Paging mode: ");
+                    writer.WriteLine(IsPagingMode() ? "ENABLED" : "Disabled");
+                    writer.WriteLine();
+
+
+                    while (!isEndOfPaging)
+                    {
+                        WriteDebugInfo(
+                            $"Command '{Name}': IsPagingMode={IsPagingMode()}; GetCurrentPage={GetCurrentPage()}; GetItemsPerPage={GetItemsPerPage()};");
+
+                        int nCnt = 0;
+                        isEndOfPaging = !IsPagingMode();
+                        var ordinal = (GetCurrentPage() - 1) * GetItemsPerPage();
+                        foreach (var item in _items.Skip(GetCurrentPage() - 1).Take(GetItemsPerPage()))
+                        {
+                            writer.Write($"{ordinal + 1}. :");
+                            OnWriteEntry(writerGreen, item);
+                            ordinal++;
+                            nCnt++;
+                        }
+
+                        writer.WriteLine();
+                        if (IsPagingMode()) 
+                            writer.WriteLine($"List shows {nCnt}/{_items.Count} items.");
+                        else
+                            writer.WriteLine($"List shows {nCnt} items.");
+                        
+                        if (IsPagingMode())
+                        {
+                            writer.WriteLine($"Showing page {GetCurrentPage()}/{GetPagesCount()}.");
+                            using (var writerCyan = new ConsoleWriter(ConsoleColor.Cyan))
+                            {
+                                using (var writerWhite = new ConsoleWriter(ConsoleColor.White))
+                                {
+                                    var isSelected = false;
+                                    while (!isSelected)
+                                    {
+                                        writerWhite.WriteLine(
+                                            $"Type special character [{QConsole.Defaults.RoleCharacters.InputIncrementPageCharacter}/{QConsole.Defaults.RoleCharacters.InputDecrementPageCharacter}/{QConsole.Defaults.RoleCharacters.InputFirstPageCharacter}/{QConsole.Defaults.RoleCharacters.InputLastPageCharacter}] or direct page value or ENTER to skip.");
+                                        writerCyan.Write($"[{GetFirstPage()}-{GetLastPage()}]>");
+                                        var pageString = writerCyan.ReadLine().Trim();
+                                        try
+                                        {
+                                            isSelected = true;
+                                            if (pageString == QConsole.Defaults.RoleCharacters
+                                                    .InputIncrementPageCharacter)
+                                            {
+                                                //increment page
+                                                if (CheckPage(GetCurrentPage() + 1))
+                                                    SetCurrentPage(GetCurrentPage() + 1);
+                                            }
+                                            else if (pageString == QConsole.Defaults.RoleCharacters
+                                                         .InputDecrementPageCharacter)
+                                            {
+                                                //decrement page
+                                                if (CheckPage(GetCurrentPage() - 1))
+                                                    SetCurrentPage(GetCurrentPage() - 1);
+                                            }
+                                            else if (pageString == QConsole.Defaults.RoleCharacters
+                                                         .InputFirstPageCharacter)
+                                            {
+                                                //first page
+                                                SetCurrentPage(GetFirstPage());
+                                            }
+                                            else if (pageString ==
+                                                     QConsole.Defaults.RoleCharacters.InputLastPageCharacter)
+                                            {
+                                                //last page
+                                                SetCurrentPage(GetLastPage());
+                                            }
+                                            else if (pageString ==
+                                                     QConsole.Defaults.RoleCharacters.InputExitPageCharacter)
+                                            {
+                                                //exit page
+                                                isEndOfPaging = true;
+                                                continue;
+                                            }
+                                            else
+                                            {
+                                                //direct page
+                                                var pageNo = int.Parse(pageString);
+                                                SetCurrentPage(pageNo);
+                                            }
+                                        }
+                                        catch (Exception e)
+                                        {
+                                            using (var writerRed = new ConsoleWriter(ConsoleColor.Red))
+                                            {
+                                                writerRed.Write("Error:").WriteLine(e.Message);
+                                            }
+
+                                            isSelected = false;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            return incommingResult;
+        }
+
+        
+        protected abstract void OnWriteEntry(ConsoleWriter writer, ISelectionEntry entry);
+
+        protected override IEnumerable<AbstractArgument> OnSetupArguments()
+        {
+            var arguments = base.OnSetupArguments().ToList();
+            arguments.AddRange(new[]
+            {
+                new FlagArgument(Constants.Arguments.Lists.PageMode.Code,
+                    Constants.Arguments.Lists.PageMode.Description,
+                    Constants.Arguments.Lists.PageMode.Hint, false),
+                new NamedArgument(Constants.Arguments.Lists.ItemsPerPage.Code,
+                    Constants.Arguments.Lists.ItemsPerPage.Description,
+                    Constants.Arguments.Lists.ItemsPerPage.Hint,
+                    TypeValuesEnum.Integer,
+                    QConsole.Defaults.Arguments.ItemsPerPage.ToString(), false),
+                new NamedArgument(Constants.Arguments.Lists.Page.Code,
+                    Constants.Arguments.Lists.Page.Description,
+                    Constants.Arguments.Lists.Page.Hint,
+                    TypeValuesEnum.Integer,
+                    "1", false),
+            });
+            return arguments;
+        }
+
+        protected void EnableDefaultPagingMode()
+        {
+            var argPageMode = GetArgument(Constants.Arguments.Lists.PageMode.Code);
+            argPageMode.DefaultValue.Set(true);
+            argPageMode.SetValueAsDefault();
+        }
+        protected void DisableDefaultPagingMode()
+        {
+            var argPageMode = GetArgument(Constants.Arguments.Lists.PageMode.Code);
+            argPageMode.DefaultValue.Set(false);
+            argPageMode.SetValueAsDefault();
+        }
+        #endregion
+
+        #region *** Private Operations ***
+
+        private bool IsPagingMode()
+        {
+            var argPageMode = GetArgument(Constants.Arguments.Lists.PageMode.Code);
+            return (bool) argPageMode.Value.Get();
+        }
+
+        private int GetItemsPerPage()
+        {
+            if (!IsPagingMode())
+                return _items.Count;
+            var argPageItems = GetArgument(Constants.Arguments.Lists.ItemsPerPage.Code);
+            return (int) argPageItems.Value.Get();
+        }
+
+        private int GetCurrentPage()
+        {
+            var argPage = GetArgument(Constants.Arguments.Lists.Page.Code);
+            return (int) argPage.Value.Get();
+        }
+
+        private void SetCurrentPage(int page)
+        {
+            if (!CheckPage(page))
+                throw new Exception($"Page value must be inside interval <{GetFirstPage()};{GetLastPage()}>.");
+            var argPage = GetArgument(Constants.Arguments.Lists.Page.Code);
+            argPage.Value.Set(page);
+        }
+
+        private bool CheckPage(int page)
+        {
+            return !(page < GetFirstPage() || page > GetLastPage());
+        }
+
+        private int GetFirstPage()
+        {
+            return 1;
+        }
+        private int GetLastPage()
+        {
+            return GetPagesCount();
+        }
+
+        private int GetPagesCount()
+        {
+            return (_items.Count / GetItemsPerPage()) + 1;
+        }
+        private void SetupPaging()
+        {
+            if (!IsPagingMode())
+            {
+                var argPageItems = GetArgument(Constants.Arguments.Lists.ItemsPerPage.Code);
+                argPageItems.Value.Set(_items.Count);
+                SetCurrentPage(1);
+            }
+        }
+        #endregion
+
+    }
+}

+ 127 - 0
Common/qdr.fnd.core.qconsole/Command/Base/AbstractSelectionCommand.cs

@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.QConsole.Argument;
+using Quadarax.Foundation.Core.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Command.Base
+{
+    public abstract class AbstractSelectionCommand : AbstractListCommand
+    {
+        #region *** Private fields ***
+        private int _maxSelections;
+        private int _minSelections;
+        private IList<ISelectionEntry> _selectedItems;
+        
+        #endregion
+
+        #region *** Properties ***
+        protected abstract bool IsStoredToGlobal { get; } 
+        protected int MaxSelections => _maxSelections;
+        protected int MinSelections => _minSelections;
+        public ISelectionEntry[] SelectedItems => _selectedItems.ToArray();
+        #endregion
+
+        #region *** Constructors ***
+        protected AbstractSelectionCommand(Engine engine,int minSelection, int maxSelection) : base(engine)
+        {
+            if (maxSelection==0)
+                throw new ArgumentOutOfRangeException(nameof(maxSelection),$"Max selections value must be bigger than zero in command '{Name}'.");
+            if (minSelection==0)
+                throw new ArgumentOutOfRangeException(nameof(minSelection),$"Min selections value must be bigger than zero in command '{Name}'.");
+            if (minSelection > maxSelection)
+                throw new ArgumentOutOfRangeException(nameof(maxSelection),$"Max selections value must be bigger than Min selection value in command '{Name}'.");
+
+            _maxSelections = maxSelection;
+            _minSelections = minSelection;
+            _selectedItems = new List<ISelectionEntry>();
+        }
+        #endregion
+
+        #region *** Public Operations ***
+        
+
+        public void ClearSelected()
+        {
+            _selectedItems.Clear();
+            WriteDebugInfo($"Command '{Name}' clears selected items.");
+        }
+        #endregion
+
+        #region *** Protected Overrides ***
+        protected override IEnumerable<AbstractArgument> OnSetupArguments()
+        {
+            var arguments = base.OnSetupArguments().ToList();
+            arguments.AddRange(
+            new []
+            {
+                new FlagArgument(Constants.Arguments.Selection.Code,
+                    Constants.Arguments.Selection.Description,
+                    Constants.Arguments.Selection.Hint, false)
+            });
+            return arguments;
+        }
+
+        protected override Result EndExecute(Result incommingResult)
+        {
+            var result = base.EndExecute(incommingResult);
+            if (!result.IsSuccess)
+                return result;
+
+            ClearSelected();
+            var nCnt = Items.Count();
+            var selectionEnabled = GetArgument(Constants.Arguments.Selection.Code);
+            if ((bool) selectionEnabled.Value.Get() == false)
+                return result;
+            using (var writer = new ConsoleWriter(ConsoleColor.White))
+            {
+                using (var writerCyan = new ConsoleWriter(ConsoleColor.Cyan))
+                {
+                    writer.WriteLine($"Select ordinal values separated by '{Engine.Configuration.CharacterSelectionInputValueSeparator}'...");
+                    writer.WriteLine($"Must be selected at least {MinSelections} ordinals and maximal {MaxSelections} ordinals.");
+                    writerCyan.Write($"[1-{nCnt}]>");
+                    var ordinalString = writerCyan.ReadLine();
+                    var ordinals = ordinalString.Split(new[] {Engine.Configuration.CharacterSelectionInputValueSeparator}, StringSplitOptions.RemoveEmptyEntries);
+                    
+                    if (!(MinSelections<=ordinals.Length && ordinals.Length <= MaxSelections))
+                            throw new Exception($"Number of ordinals must be in interval <{MinSelections};{MaxSelections}>. Current number of ordinals is {ordinals.Length}.");
+
+                    foreach (var ordinal in ordinals.Select(x=>int.Parse(x)))
+                    {
+                        if (ordinal<0 || ordinal > nCnt)
+                            throw new Exception($"Ordinal {ordinal} is out of scope interval <1;{nCnt}>.");
+                        _selectedItems.Add(GetItem(ordinal-1));
+                    }
+
+                    writer.WriteLine($"Selected {_selectedItems.Count} ordinals.");
+
+                    if (IsStoredToGlobal)
+                        Engine.AppendSelection(_selectedItems.ToArray());
+                }
+            }
+
+            return result;
+        }
+
+        protected void EnableDefaultSelectionMode()
+        {
+            var argSelectionMode = GetArgument(Constants.Arguments.Selection.Code);
+            argSelectionMode.DefaultValue.Set(true);
+            argSelectionMode.SetValueAsDefault();
+        }
+        protected void DisableDefaultSelectionMode()
+        {
+            var argSelectionMode = GetArgument(Constants.Arguments.Selection.Code);
+            argSelectionMode.DefaultValue.Set(false);
+            argSelectionMode.SetValueAsDefault();
+        }
+
+        #endregion
+
+        #region *** Private Operations ***
+
+        #endregion
+
+    }
+}

+ 11 - 0
Common/qdr.fnd.core.qconsole/Command/Base/ISelectionEntry.cs

@@ -0,0 +1,11 @@
+namespace Quadarax.Foundation.Core.QConsole.Command.Base
+{
+    public interface ISelectionEntry
+    {
+        string GetIdentifier();
+        string GetDisplayValue();
+
+        object GetPropertyValue(string propertyName);
+        string GetPropertyValueAsString(string propertyName);
+    }
+}

+ 31 - 0
Common/qdr.fnd.core.qconsole/Command/Defaults/CmdClear.cs

@@ -0,0 +1,31 @@
+using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.QConsole.Attributes;
+using Quadarax.Foundation.Core.QConsole.Command.Base;
+using Quadarax.Foundation.Core.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Command.Defaults
+{
+    [CommandDefinition]
+    public class CmdClear: AbstractCommand
+    {
+        #region *** Properties ***
+        public override string Name => Constants.Commands.Clear.Name;
+        public override string Description => Constants.Commands.Clear.Description;
+        #endregion
+
+
+        #region *** Constructor ***
+        public CmdClear(Engine engine) : base(engine)
+        {
+        }
+        #endregion
+
+        #region *** Protected overrides ***
+        protected override Result OnExecute()
+        {
+            ConsoleWriter.Clear();
+            return new Result();
+        }
+        #endregion
+    }    
+}

+ 29 - 0
Common/qdr.fnd.core.qconsole/Command/Defaults/CmdExit.cs

@@ -0,0 +1,29 @@
+using Quadarax.Foundation.Core.QConsole.Attributes;
+using Quadarax.Foundation.Core.QConsole.Command.Base;
+using Quadarax.Foundation.Core.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Command.Defaults
+{
+    [CommandDefinition]
+    public class CmdExit : AbstractCommand
+    {
+        #region *** Properties ***
+        public override string Name => Constants.Commands.Exit.Name;
+        public override string Description => Constants.Commands.Exit.Description;
+        #endregion
+
+        #region *** Constructors ***
+        public CmdExit(Engine engine) : base(engine)
+        {
+        }
+        #endregion
+       
+        #region *** Protected overrides ***
+        protected override Result OnExecute()
+        {
+            Engine.Stop();
+            return new Result();
+        }
+        #endregion
+    }
+}

+ 190 - 0
Common/qdr.fnd.core.qconsole/Command/Defaults/CmdHelp.cs

@@ -0,0 +1,190 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.QConsole.Argument;
+using Quadarax.Foundation.Core.QConsole.Attributes;
+using Quadarax.Foundation.Core.QConsole.Command.Base;
+using Quadarax.Foundation.Core.QConsole.Extensions;
+using Quadarax.Foundation.Core.QConsole.Value;
+using Quadarax.Foundation.Core.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Command.Defaults
+{
+    [CommandDefinition]
+    public class CmdHelp : AbstractCommand
+    {
+        #region *** Properties ***
+        public override string Name => Constants.Commands.Help.Name;
+        public override string Description => Constants.Commands.Help.Description;
+        #endregion
+
+        #region *** Constructors ***
+        public CmdHelp(Engine engine) : base(engine)
+        {
+        }
+        #endregion
+
+        #region *** Protected overrides ***
+        protected override Result OnExecute()
+        {
+            if (!GetArgument(Constants.Commands.Help.ArgCommandName.Code).Value.HasValue)
+            {
+                if (!Engine.Configuration.IsConsoleDebug)
+                {
+                    using (var writer = new ConsoleWriter(ConsoleColor.White))
+                    {
+                        writer.WriteLine(
+                            "To enable debug mode - more verbosity - use argument \"-dbg\" at the end of line.");
+                    }
+                }
+
+                using (var writer = new ConsoleWriter(ConsoleColor.Yellow))
+                {
+                    writer.WriteLine("Console commands list:");
+                }
+
+                using (var writer = new ConsoleWriter(ConsoleColor.Green))
+                {
+                    foreach (var command in Engine.Commands)
+                    {
+                        writer.WriteLine($"{command.Name}\t{command.Description}");
+                    }
+
+                    writer.WriteLine();
+                }
+
+                using (var writer = new ConsoleWriter(ConsoleColor.Yellow))
+                {
+                    writer.WriteLine($"To view more info for specific command type {Name} <{GetArgument(Constants.Commands.Help.ArgCommandName.Code).Hint}>");
+                }
+
+
+                if (GetArgumentValueOrDefault<bool>(Constants.Commands.Help.ArgFlagAll.Code))
+                {
+                    foreach (var command in Engine.Commands)
+                    {
+                        ShowCommandHelp(command);
+                        WriteInfo("---");
+                    }
+                }
+
+            }
+        
+            else
+            {
+                var argument = GetArgument(Constants.Commands.Help.ArgCommandName.Code);
+                var command = Engine.GetCommand(argument.Value.AsString());
+                if (command == null)
+                    throw new Exception($"Unkonwn command '{argument.Value.AsString()}'");
+                ShowCommandHelp(command);
+
+            }
+            return new Result();
+        }
+
+        protected override IEnumerable<AbstractArgument> OnSetupArguments()
+        {
+            var result = base.OnSetupArguments().ToList();
+            result.AddRange( new AbstractArgument[]
+            {
+                new OrdinalArgument(0, true, 
+                    Constants.Commands.Help.ArgCommandName.Code,
+                    Constants.Commands.Help.ArgCommandName.Description,
+                    Constants.Commands.Help.ArgCommandName.Hint,
+                    TypeValuesEnum.String,
+                    string.Empty,
+                    false),
+                new FlagArgument(Constants.Commands.Help.ArgFlagAll.Code,
+                    Constants.Commands.Help.ArgFlagAll.Description,
+                    Constants.Commands.Help.ArgFlagAll.Hint,
+                    false
+                    )
+            });
+            return result;
+        }
+        #endregion
+
+        #region *** Private Operations ***
+
+        private void ShowCommandHelp(AbstractCommand command)
+        {
+            using (var writer = new ConsoleWriter(ConsoleColor.Green))
+            {
+                using (var writerWhite = new ConsoleWriter(ConsoleColor.White))
+                {
+                    writer.Write($"Command: \t");
+                    writerWhite.WriteLine(command.Name);
+                    writer.Write($"Description: \t");
+                    writerWhite.WriteLine(command.Description);
+                    writer.Write($"Parameters: \t");
+                    writerWhite.WriteLine((command.Arguments.Length == 0 ? "none" : string.Empty));
+                    foreach (var arg in command.Arguments.OrderBy(x => x.IsPositional() ? 0 : 1))
+                    {
+                        var optional = arg.IsMandatory ? "Mandatory." : "Optional.";
+                        var argumentName = arg.IsPositional()
+                            ? $"<{arg.Code}>"
+                            : $"{Engine.Configuration.CharacterNamedArgumentSeparator}{arg.Code}";
+                        writer.WriteLine($"{argumentName}\t{optional}{arg.Description}");
+                    }
+
+                    var usage = new StringBuilder();
+                    writer.WriteLine();
+                    writer.WriteLine("Usage:");
+                    writer.Write($"\t{Engine.Configuration.CharacterLineIntroduce}");
+                    if (!string.IsNullOrEmpty(command.CustomUsage))
+                    {
+                        usage.Append(command.CustomUsage).AppendLine();
+                    }
+                    else
+                    {
+                        usage.Append(command.Name);
+                        foreach (var arg in command.Arguments.OrderBy(x => x.IsPositional() ? 0 : 1))
+                        {
+                            usage.Append(" ");
+                            usage.Append(GetArgumentEntryAsDescription(arg));
+                        }
+                    }
+
+                    writerWhite.WriteLine(usage.ToString());
+
+                    if (!string.IsNullOrEmpty(command.Notes))
+                    {
+                        writer.WriteLine();
+                        writer.Write($"Notes: \t");
+                        writer.Write($"\t{command.Notes}");
+                    }
+
+                    if (!string.IsNullOrEmpty(command.Examples))
+                    {
+                        writer.WriteLine();
+                        writer.Write($"Examples: \t");
+                        writer.Write($"\t{command.Examples}");
+                    }
+                }
+            }
+        }
+
+        private string GetArgumentEntryAsDescription(AbstractArgument arg)
+        {
+            var argumentName = $"{Engine.Configuration.CharacterNamedArgumentSeparator}{arg.Code}";
+
+            string argumentBody;
+            if (arg.IsCodeAccessAllowed() && arg.IsPositional())
+                argumentBody = "[" + argumentName + Engine.Configuration.CharacterNamedArgumentValueSeparator + "]" + arg.Hint;
+            else if (arg.IsPositional())
+                argumentBody = arg.Hint;
+            else
+                argumentBody = argumentName + Engine.Configuration.CharacterNamedArgumentValueSeparator + arg.Hint;
+
+            if (!arg.IsMandatory)
+            {
+                argumentBody = "[" + argumentBody + "]";
+            }
+
+            return argumentBody;
+        }
+        #endregion
+    }
+}

+ 87 - 0
Common/qdr.fnd.core.qconsole/Command/Defaults/CmdPrint.cs

@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.QConsole.Argument;
+using Quadarax.Foundation.Core.QConsole.Attributes;
+using Quadarax.Foundation.Core.QConsole.Command.Base;
+using Quadarax.Foundation.Core.QConsole.Value;
+using Quadarax.Foundation.Core.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Command.Defaults
+{
+    [CommandDefinition]
+    public class CmdPrint : AbstractCommand
+    {
+        public CmdPrint(Engine engine) : base(engine)
+        {
+        }
+
+        public override string Name => Constants.Commands.Print.Name;
+        public override string Description => Constants.Commands.Print.Description;
+
+        protected override IEnumerable<AbstractArgument> OnSetupArguments()
+        {
+            var arguments = base.OnSetupArguments().ToList();
+            arguments.AddRange(
+                new AbstractArgument []
+                {
+                    new OrdinalArgument(0,
+                        false,
+                        Constants.Commands.Print.ArgCommandValue.Code,
+                        Constants.Commands.Print.Description,
+                        Constants.Commands.Print.ArgCommandValue.Hint,
+                        TypeValuesEnum.String,
+                        string.Empty,
+                        true),
+
+                    new FlagArgument(Constants.Commands.Print.ArgCommandClipboard.Code,
+                        Constants.Commands.Print.ArgCommandClipboard.Description,
+                        Constants.Commands.Print.ArgCommandClipboard.Hint,
+                        false), 
+                });
+            return arguments;
+        }
+        protected override Result OnExecute()
+        {
+            var result = new Result();
+            using (var writerGreen = new ConsoleWriter(ConsoleColor.Green))
+            {
+                using (var writerYellow = new ConsoleWriter(ConsoleColor.Yellow))
+                {
+                    var valueArgument = GetArgument(0);
+                    var value = valueArgument.Value.AsString();
+                    if (!value.StartsWith(QConsole.Defaults.RoleCharacters.SelectionVariablePrefixCharacter))
+                        throw new Exception($"Variable is defined as {QConsole.Defaults.RoleCharacters.SelectionVariablePrefixCharacter}<selection_ordinal>.<property_name>");
+
+                    var parts = value.Split(
+                        new string[]
+                        {
+                            QConsole.Defaults.RoleCharacters.SelectionVariablePrefixCharacter,
+                            QConsole.Defaults.RoleCharacters.SelectionVariablePropertyCharacter
+                        }, StringSplitOptions.RemoveEmptyEntries);
+                    if (parts.Length!=2)
+                        throw new Exception($"Variable is defined as {QConsole.Defaults.RoleCharacters.SelectionVariablePrefixCharacter}<selection_ordinal>.<property_name>");
+
+                        
+                    var ordinal = int.Parse(parts[0]);
+                    var selection = Engine.GetSelection(ordinal);
+                    if (selection == null)
+                        throw new Exception($"Selection variable '{value}' is not defined.");
+
+                    writerGreen.Write(value);
+                    writerGreen.Write(" = ");
+                    writerYellow.WriteLine(selection.GetPropertyValueAsString(parts[1]));
+
+                    var argument = GetArgument(Constants.Commands.Print.ArgCommandClipboard.Code);
+                    if ((bool) argument.Value.Get())
+                    {
+                        writerGreen.WriteLine("Value was stored in clipboard.");
+                    }
+                }
+            }
+
+            return result;
+        }
+    }
+}

+ 74 - 0
Common/qdr.fnd.core.qconsole/Command/Defaults/CmdSelection.cs

@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.QConsole.Argument;
+using Quadarax.Foundation.Core.QConsole.Attributes;
+using Quadarax.Foundation.Core.QConsole.Command.Base;
+using Quadarax.Foundation.Core.QConsole.Value;
+using Quadarax.Foundation.Core.Value;
+
+namespace Quadarax.Foundation.Core.QConsole.Command.Defaults
+{
+    [CommandDefinition]
+    public class CmdSelection : AbstractListCommand
+    {
+        #region *** Properties ***
+        public override string Name => Constants.Commands.Selection.Name;
+        public override string Description => Constants.Commands.Selection.Description;
+        #endregion
+
+        #region *** Constructors ***
+        public CmdSelection(Engine engine) : base(engine)
+        {
+        }
+        #endregion
+       
+        #region *** Protected overrides ***
+
+        protected override IEnumerable<AbstractArgument> OnSetupArguments()
+        {
+            var arguments = base.OnSetupArguments().ToList();
+            arguments.AddRange(
+                new []
+                {
+                    new FlagArgument(Constants.Arguments.Selection.List.Code,
+                        Constants.Arguments.Selection.List.Description, Constants.Arguments.Selection.List.Hint, true),
+                    new FlagArgument(Constants.Arguments.Selection.Clear.Code,
+                        Constants.Arguments.Selection.Clear.Description, Constants.Arguments.Selection.Clear.Hint,
+                        false),
+                    new NamedArgument(Constants.Arguments.Selection.Delete.Code,
+                        Constants.Arguments.Selection.Delete.Description, Constants.Arguments.Selection.Delete.Hint,
+                        TypeValuesEnum.String, string.Empty, false),
+                });
+            return arguments;
+        }
+
+        protected override void OnWriteEntry(ConsoleWriter writer, ISelectionEntry entry)
+        {
+            writer.Write("ID: ");
+            writer.Write(entry.GetIdentifier());
+            writer.Write("\t");
+            writer.Write("Value: ");
+            writer.WriteLine(entry.GetDisplayValue());
+        }
+
+        protected override Result EndExecute(Result incommingResult)
+        {
+            var result =  base.EndExecute(incommingResult);
+            using (var writerWhite = new ConsoleWriter(ConsoleColor.White))
+            {
+                writerWhite.WriteLine(
+                    $"For selection variable usage use {QConsole.Defaults.RoleCharacters.SelectionVariablePrefixCharacter}<selection_ordinal>.<property_name> in console.");
+            }
+            return result;
+        }
+
+        protected override Result OnExecute()
+        {
+            SetModel(Engine.Selections);
+            return new Result();
+        }
+        #endregion
+    }
+}

+ 234 - 0
Common/qdr.fnd.core.qconsole/Configuration/StartupConfiguration.cs

@@ -0,0 +1,234 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Xml.XPath;
+using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.QConsole.Handlers;
+
+namespace Quadarax.Foundation.Core.QConsole.Configuration
+{
+    public class StartupConfiguration
+    {
+        #region *** Private Fields ***
+        private bool _isConsoleDebug;
+        private string[] _defaultCommands = {"CmdClear", "CmdExit", "CmdPrint", "CmdSelection"};
+
+        private readonly IList<string> _disabledCommands = new List<string>();
+        #endregion
+
+        #region *** Properties ***
+        /// <summary>
+        /// Name of console application, If not defined uses default name from entryAssembly.
+        /// </summary>
+        public string ConsoleName { get; }
+        /// <summary>
+        /// Console application version. If not defined uses version of entryAssembly.
+        /// </summary>
+        public Version ConsoleVersion { get; }
+        /// <summary>
+        /// Console application copyright message. If not set skip this info.
+        /// </summary>
+        public string ConsoleCopyright { get; set; }
+        /// <summary>
+        /// Defines if console is initialized from XML definition.
+        /// </summary>
+        public bool IsInitFromXml { get; }
+
+        /// <summary>
+        /// Left introducing of interactive mode character.
+        /// </summary>
+        public string CharacterLineIntroduce { get; set; }
+
+        /// <summary>
+        /// Separator between two ordinal arguments
+        /// </summary>
+        public string CharacterOrdinalArgumentSeparator { get; set; }
+
+        /// <summary>
+        /// Named argument prefix character.
+        /// </summary>
+        public string CharacterNamedArgumentSeparator { get; set; }
+        /// <summary>
+        /// Named argument postfix character {defines end of argument code and value)
+        /// </summary>
+        public string CharacterNamedArgumentValueSeparator { get; set; }
+        /// <summary>
+        /// Start end end string value character
+        /// </summary>
+        public string CharacterTextValueBraceSeparator { get; set; }
+
+        /// <summary>
+        /// Separator between two selection inputs
+        /// </summary>
+        public string CharacterSelectionInputValueSeparator { get; set; }
+
+        /// <summary>
+        /// Date input/output value format
+        /// </summary>
+        public string DateFormat { get; set; }
+        /// <summary>
+        /// Time input/output value format
+        /// </summary>
+        public string TimeFormat { get; set; }
+        /// <summary>
+        /// Defines if interactive mode is enabled
+        /// </summary>
+        public bool AllowInteractive { get; set; }
+        /// <summary>
+        /// Defines if initial variables is allowed for interactive mode.
+        /// </summary>
+        public bool AllowPreset { get; set; }
+
+        /// <summary>
+        /// Defines assembly list where custom commands are defined (in case explicit command definition).
+        /// </summary>
+        public Assembly[] CommandDefinitionAssebmly { get; set; }
+
+        /// <summary>
+        /// Returns name of command classes that will be disabled (hidden)
+        /// </summary>
+        public string[] DisabledCommands => _disabledCommands.ToArray();
+
+        /// <summary>
+        /// Defines if waits on key at the end of process in non-interactive mode (inline mode)
+        /// </summary>
+        public bool WaitOnKeyInNonInteractiveMode { get; set; }
+
+        /// <summary>
+        /// Defines if show status of engine and command context before every command executed.
+        /// </summary>
+        public bool ShowStatusOnEveryCommand { get; set; }
+
+
+        public bool UseDefaultHandlers { get; set; }
+
+        /// <summary>
+        /// Handler when no arguments input specified. If not set then do nothing.
+        /// </summary>
+        public NothingToDo HandlerNothingToDo { get; set; }
+
+        public bool IsConsoleDebug {
+            get
+            {
+                return _isConsoleDebug;
+            }
+            set 
+            { 
+                _isConsoleDebug = value;
+                DebugConsoleWriter.IsWriteDebugEnabled = value;
+            }
+        }
+        #endregion
+
+        #region *** Constructor ***
+
+        public StartupConfiguration(string consoleName, Version consoleVersion)
+        {
+            ConsoleName = consoleName;
+            ConsoleVersion = consoleVersion;
+            IsInitFromXml = false;
+            InitDefaults();
+        }
+
+        public StartupConfiguration(string consoleXmlFileName)
+        {
+            IsInitFromXml = true;
+            InitDefaults();
+        }
+
+        public StartupConfiguration(XPathNavigator configurationNavigator)
+        {
+            IsInitFromXml = true;
+            InitDefaults();
+        }
+        #endregion
+
+        #region *** Public Operations ***
+        public StartupConfiguration EnableDebugMode()
+        {
+            IsConsoleDebug = true;
+            return this;
+        }
+        public StartupConfiguration DisableDebugMode()
+        {
+            IsConsoleDebug = false;
+            return this;
+        }
+
+        public StartupConfiguration DisableDefaultCommands()
+        {
+            return DisableCommands(_defaultCommands);
+        }
+
+        public StartupConfiguration EnableDefaultCommands()
+        {
+            return EnableCommands(_defaultCommands);
+        }
+
+        public StartupConfiguration EnableCommands(params string[] commandClassNames)
+        {
+            if (commandClassNames == null)
+                return this;
+
+            foreach (var className in commandClassNames)
+            {
+                if (_disabledCommands.Contains(className))
+                    _disabledCommands.Remove(className);
+            }
+            return this;
+        }
+
+        public StartupConfiguration DisableCommands(params string[] commandClassNames)
+        {
+            if (commandClassNames == null)
+                return this;
+            foreach (var className in commandClassNames)
+            {
+                if (!_disabledCommands.Contains(className))
+                    _disabledCommands.Add(className);
+            }
+
+            return this;
+        }
+
+        #endregion
+
+        #region *** Private Operations ***
+        private void InitDefaults()
+        {
+            CharacterLineIntroduce = Defaults.RoleCharacters.ConsoleLineIntroduce;
+            CharacterOrdinalArgumentSeparator = Defaults.RoleCharacters.OrdinalArgumentSeparator;
+            CharacterNamedArgumentSeparator = Defaults.RoleCharacters.NamedArgumentSeparator;
+            CharacterNamedArgumentValueSeparator = Defaults.RoleCharacters.NamedArgumentValueSeparator;
+            CharacterTextValueBraceSeparator = Defaults.RoleCharacters.TextValueBraceSeparator;
+            CharacterSelectionInputValueSeparator = Defaults.RoleCharacters.InputSelectionValueSeparator;
+
+            DateFormat = Defaults.Formats.DateFormat;
+            TimeFormat = Defaults.Formats.TimeFormat;
+
+            AllowInteractive = Defaults.Console.InteractiveAllowed;
+            AllowPreset = Defaults.Console.PresetAllowed;
+            IsConsoleDebug = Defaults.Console.ConsoleDebugMode;
+            WaitOnKeyInNonInteractiveMode = Defaults.Console.WaitOnKeyInNonInteractiveMode;
+            ShowStatusOnEveryCommand = Defaults.Console.ShowStatusOnEveryCommand;
+            UseDefaultHandlers = Defaults.Console.UseDefaultHadlers;
+
+            if (UseDefaultHandlers)
+            {
+                HandlerNothingToDo += engine =>
+                {
+                    using (var writer = new ConsoleWriter(ConsoleColor.Yellow))
+                    {
+                        writer.WriteLine("Nothing to do.");
+                    }
+                    using (var writer = new ConsoleWriter(ConsoleColor.DarkGreen))
+                    {
+                        writer.WriteLine("Put some arguments to do something. For example -help to list commands and arguments.");
+                    }
+                };
+            }
+        }
+        #endregion
+    }
+}

+ 128 - 0
Common/qdr.fnd.core.qconsole/Constants.cs

@@ -0,0 +1,128 @@
+namespace Quadarax.Foundation.Core.QConsole
+{
+    public static class Constants
+    {
+
+        public static class Console
+        {
+            public const string DebugModeExplicitArg = "-dbg";
+        }
+
+        public static class Arguments
+        {
+            public static class Selection
+            {
+                public const string Code = "s";
+                public const string Description = "Execute command with selection mode. You will be able to select values.";
+                public const string Hint = "<enable>";
+
+                public static class Clear
+                {
+                    public const string Code = "c";
+                    public const string Description = "Clears all global selection cache.";
+                    public const string Hint = "<enable>";
+    
+                }
+
+                public static class Delete
+                {
+                    public const string Code = "d";
+                    public const string Description = "Delete specific ordinals from global selection cache.";
+                    public const string Hint = "<ordinal_values>";
+                }
+                public static class List
+                {
+                    public const string Code = "l";
+                    public const string Description = "Disable list global selection cache.";
+                    public const string Hint = "<disaled>";
+                }
+            }
+
+            public static class Lists
+            {
+                public static class PageMode
+                {
+                    public const string Code = "p";
+                    public const string Description = "Enables paging mode. List shows items by pages.";
+                    public const string Hint = "<enables>";
+                }
+                public static class ItemsPerPage
+                {
+                    public const string Code = "pp";
+                    public const string Description = "Defines number of items shown in one page. Use only in Paging mode.";
+                    public const string Hint = "<count_per_page>";
+                }
+
+                public static class Page
+                {
+                    public const string Code = "pg";
+                    public const string Description = "Defines shown default page. Use only in Paging mode. If 0, then inactive.";
+                    public const string Hint = "<default_page>";
+                }
+
+            }
+        }
+
+        public static class Commands
+        {
+            public static class Help
+            {
+
+                public const string Name = "HELP";
+                public const string Description = "Shows list of available commands and arguments.";
+
+                public static class ArgCommandName
+                {
+                    public const string Code = "n";
+                    public const string Hint = "command_name";
+                    public const string Description = "Name of command to list specification.";
+                }
+
+                public static class ArgFlagAll
+                {
+                    public const string Code = "all";
+                    public const string Hint = "show_all";
+                    public const string Description = "Flag if set dump all commands help.";
+                }
+            }
+
+            public static class Exit
+            {
+                public const string Name = "EXIT";
+                public const string Description = "Exits interactive console.";
+            }
+
+            public static class Clear
+            {
+                public const string Name = "CLEAR";
+                public const string Description = "Clears console window.";
+            }
+
+            public static class Selection
+            {
+                public const string Name = "SELECTION";
+                public const string Description = "Shows global selection cache and provide operations";
+            }
+            
+            public static class Print
+            {
+                public const string Name = "PRINT";
+                public const string Description = "Print outs variable value to console";
+
+                public static class ArgCommandClipboard
+                {
+                    public const string Code = "c";
+                    public const string Hint = "enabled";
+                    public const string Description = "Copy output to clipboard.";
+                }
+                public static class ArgCommandValue
+                {
+                    public const string Code = "v";
+                    public const string Hint = "value";
+                    public const string Description = "Variable name code @<selection_ordinal>.";
+                }
+            }
+
+        }
+    }
+}

+ 18 - 0
Common/qdr.fnd.core.qconsole/Context/DefaultCommandContext.cs

@@ -0,0 +1,18 @@
+using Quadarax.Foundation.Core.Object;
+
+namespace Quadarax.Foundation.Core.QConsole.Context
+{
+    public class DefaultCommandContext : DisposableObject, ICommandContext
+    {
+        protected override void OnDisposing()
+        {
+        }
+
+        public string Status => "READY";
+
+        public override string ToString()
+        {
+            return "Default empty command context";
+        }
+    }
+}

+ 23 - 0
Common/qdr.fnd.core.qconsole/Context/DefualtEngineContext.cs

@@ -0,0 +1,23 @@
+using Quadarax.Foundation.Core.Object;
+
+namespace Quadarax.Foundation.Core.QConsole.Context
+{
+    public class DefualtEngineContext : DisposableObject, IEngineContext
+    {
+        protected override void OnDisposing()
+        {
+        }
+
+        public ICommandContext CreateCommandContext()
+        {
+            return new DefaultCommandContext();
+        }
+
+        public string Status => "READY";
+
+        public override string ToString()
+        {
+            return "Default empty engine context";
+        }
+    }
+}

+ 6 - 0
Common/qdr.fnd.core.qconsole/Context/ICommandContext.cs

@@ -0,0 +1,6 @@
+namespace Quadarax.Foundation.Core.QConsole.Context
+{
+    public interface ICommandContext : IQConsoleContext
+    {
+    }
+}

+ 7 - 0
Common/qdr.fnd.core.qconsole/Context/IEngineContext.cs

@@ -0,0 +1,7 @@
+namespace Quadarax.Foundation.Core.QConsole.Context
+{
+    public interface IEngineContext : IQConsoleContext
+    {
+        ICommandContext CreateCommandContext();
+    }
+}

+ 9 - 0
Common/qdr.fnd.core.qconsole/Context/IQConsoleContext.cs

@@ -0,0 +1,9 @@
+using System;
+
+namespace Quadarax.Foundation.Core.QConsole.Context
+{
+    public interface IQConsoleContext : IDisposable
+    {
+        string Status { get; }
+    }
+}

+ 36 - 0
Common/qdr.fnd.core.qconsole/DebugConsoleWriter.cs

@@ -0,0 +1,36 @@
+using System;
+using Quadarax.Foundation.Core.Console;
+
+namespace Quadarax.Foundation.Core.QConsole
+{
+    public class DebugConsoleWriter : ConsoleWriter
+    {
+        public static bool IsWriteDebugEnabled { get; set; }
+
+        public DebugConsoleWriter(ConsoleColor backColor) : base(Defaults.Console.ConsoleDebugForeColor, backColor)
+        {
+        }
+
+        public DebugConsoleWriter() : base(Defaults.Console.ConsoleDebugForeColor)
+        {
+        }
+
+        public ConsoleWriter WriteDebugLine(string text)
+        {
+            if (IsWriteDebugEnabled)
+            {
+                WriteLine(text);
+            }
+            return this;
+        }
+        public ConsoleWriter WriteDebugLine()
+        {
+            if (IsWriteDebugEnabled)
+            {
+                WriteLine();
+            }
+            return this;
+        }
+
+    }
+}

+ 46 - 0
Common/qdr.fnd.core.qconsole/Defaults.cs

@@ -0,0 +1,46 @@
+using System;
+
+namespace Quadarax.Foundation.Core.QConsole
+{
+    internal class Defaults
+    {
+        public class Arguments
+        {
+            internal const int ItemsPerPage = 20;
+        }
+        internal class Console
+        {
+            internal const bool InteractiveAllowed = true;
+            internal const bool PresetAllowed = false;
+            internal const bool ConsoleDebugMode = false;
+            internal const ConsoleColor ConsoleDebugForeColor = ConsoleColor.DarkGray;
+            internal const bool DisableDefaultCommands = false;
+            internal const bool WaitOnKeyInNonInteractiveMode = false;
+            internal const bool ShowStatusOnEveryCommand = false;
+            internal const bool UseDefaultHadlers = true;
+        }
+
+        internal class Formats
+        {
+            internal const string DateFormat = "dd.MM.YYYY";
+            internal const string TimeFormat = "hh:MM:ss";
+        }
+
+        internal class RoleCharacters
+        {
+            internal const string ConsoleLineIntroduce = ">";
+            internal const string OrdinalArgumentSeparator = " ";
+            internal const string NamedArgumentSeparator = "-";
+            internal const string NamedArgumentValueSeparator = ":";
+            internal const string TextValueBraceSeparator = "\"";
+            internal const string InputSelectionValueSeparator = ",";
+            internal const string InputIncrementPageCharacter = "+";
+            internal const string InputDecrementPageCharacter = "-";
+            internal const string InputFirstPageCharacter = "f";
+            internal const string InputLastPageCharacter = "l";
+            internal const string InputExitPageCharacter = "";
+            internal const string SelectionVariablePrefixCharacter = "@";
+            internal const string SelectionVariablePropertyCharacter = ".";
+        }
+    }
+}

+ 321 - 0
Common/qdr.fnd.core.qconsole/Engine.cs

@@ -0,0 +1,321 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.QConsole.Attributes;
+using Quadarax.Foundation.Core.QConsole.Command.Base;
+using Quadarax.Foundation.Core.QConsole.Configuration;
+using Quadarax.Foundation.Core.QConsole.Context;
+
+namespace Quadarax.Foundation.Core.QConsole
+{
+    public class Engine : IDisposable
+    {
+        #region *** Private Fields ***
+        private bool _isDispoising;
+        private bool _isExitSignal;
+        private IList<AbstractCommand> _commands = new List<AbstractCommand>();
+        private StartupConfiguration _configuration;
+        private IList<ISelectionEntry> _selections = new List<ISelectionEntry>();
+        #endregion
+
+        #region *** Properties ***
+        public string[] RawArguments { get; }
+        public StartupConfiguration Configuration => _configuration;
+        public AbstractCommand[] Commands => _commands.ToArray();
+        public ISelectionEntry[] Selections => _selections.ToArray();
+
+        public IEngineContext Context { get; }
+        #endregion
+
+        #region *** Constructor ***
+        public Engine(StartupConfiguration configuration, IEngineContext context, string[] args)
+        {
+            _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
+            Context = context ?? throw new ArgumentNullException(nameof(context));
+
+            if (args == null)
+                args = new string[0];
+
+            // correction of arguments (fix " values)
+            for (var i = 0; i < args.Length; i++)
+            {
+                if (args[i].Contains(" ") && args[i].Contains(configuration.CharacterNamedArgumentValueSeparator) ||
+                    args[i].Contains(configuration.CharacterNamedArgumentSeparator) && args[i].Contains(configuration.CharacterNamedArgumentValueSeparator))
+                {
+                    var parts = args[i].Split(new[] {configuration.CharacterNamedArgumentValueSeparator},
+                        StringSplitOptions.RemoveEmptyEntries);
+                    if (parts.Length == 2)
+                        args[i] = parts[0] + configuration.CharacterNamedArgumentValueSeparator + configuration.CharacterTextValueBraceSeparator + parts[1] +
+                                  configuration.CharacterTextValueBraceSeparator;
+                    else
+                        args[i] = parts[0] + configuration.CharacterNamedArgumentValueSeparator + configuration.CharacterTextValueBraceSeparator + string.Join(":",parts.Skip(1).Take(parts.Length - 1)) +
+                                  configuration.CharacterTextValueBraceSeparator;
+                }
+            }
+
+            // Ensure if debug mode -> Enable debug mode and remove explicit argument
+            if (args.Any(x => x.Trim().ToLower() == Constants.Console.DebugModeExplicitArg))
+            {
+                configuration.EnableDebugMode();
+                var newArgs = new List<string>(args);
+                newArgs.Remove(Constants.Console.DebugModeExplicitArg);
+                args = newArgs.ToArray();
+            }
+
+
+            WriteDebugInfo($"Console '{_configuration.ConsoleName}' initialization started.");
+            WriteDebugInfo($"Engine assembly version '{Assembly.GetExecutingAssembly().GetName().Version}'.");
+            WriteDebugInfo($"IsInitFromXml is set to '{_configuration.IsInitFromXml}'.");
+
+            ShowHeader();
+
+            RawArguments = args;
+            WriteDebugInfo($"Input {args.Length} arguments appended.");
+            WriteDebugInfo($"Context set: {Context}");
+
+            var commandClasses = GetTypesWithHelpAttribute(new CommandDefinitionAttribute());
+            WriteDebugInfo($"Console found {commandClasses.Count()} command definitions.");
+
+            var paramConstrTypes = new Type[] { typeof(Engine) };
+            var paramConstrValues = new object[] { this };
+
+            foreach (var commandClass in commandClasses)
+            {
+                var command = Construct<AbstractCommand>(commandClass, paramConstrTypes, paramConstrValues);
+                _commands.Add(command);
+                WriteDebugInfo($"Command definition '{command}' added - class '{command.GetType().FullName}', assembly '{command.GetType().Assembly.GetName().Name}'.");
+            }
+
+            WriteDebugInfo("Console initialized.");
+        }
+
+        public void Start()
+        {
+            WriteDebugInfo("Console starting.");
+            var commandLineArguments = string.Join(" ", RawArguments);
+
+            using (var writer = new ConsoleWriter(ConsoleColor.White))
+            {
+                while (!_isExitSignal)
+                {
+                    var input = string.Empty;
+                    if (commandLineArguments.Length == 0 && Configuration.AllowInteractive)
+                    {
+                        // interactive command entry
+                        writer.Write(_configuration.CharacterLineIntroduce);
+                        input = System.Console.ReadLine();
+                    }
+                    else
+                    {
+                        // inline command entry
+                        input = commandLineArguments;
+                        _isExitSignal = true;
+                    }
+
+                    var args = input.Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries);
+                    if (args.Length == 0)
+                    {
+                        if (_isExitSignal == true && !Configuration.AllowInteractive &&
+                            Configuration.HandlerNothingToDo != null)
+                        {
+                            Configuration.HandlerNothingToDo.Invoke(this);
+                        }
+                        continue;
+                    }
+
+                    var command = GetCommand(args[0]);
+                    if (command == null)
+                    {
+                        using (var writerError = new ConsoleWriter(ConsoleColor.Red))
+                        {
+                            writerError.WriteLine($"Unknown command '{args[0]}'.");
+                        }
+                        continue;
+                    }
+
+                    var result = command.Execute(input);
+                    if (result.IsSuccess)
+                    {
+                        using (var writerSucc = new ConsoleWriter(ConsoleColor.Green))
+                        {
+                            writerSucc.WriteLine("Done.");
+                        }
+                    }
+                    else
+                    {
+                        using (var writerError = new ConsoleWriter(ConsoleColor.Red))
+                        {
+                            writerError.WriteLine("Error:");
+                            var e = result.ThrownException;
+
+                            if (e is AggregateException aggr)
+                            {
+                                foreach (var ex in aggr.InnerExceptions)
+                                    DumpException(writerError, ex);
+                            }
+                            else
+                                while (e != null)
+                                {                                         
+                                    writerError.WriteLine(e.Message);
+                                    e = e.InnerException;
+                                }
+                        }
+                    }
+                }
+
+                if (!Configuration.AllowInteractive && Configuration.WaitOnKeyInNonInteractiveMode)
+                {
+                    WriteDebugInfo("Waiting for the key by configuration settings...");
+                    using (var writerGreen = new ConsoleWriter(ConsoleColor.Magenta))
+                    {
+                        writerGreen.WriteLine("Press any key to close...");
+                        System.Console.ReadKey();
+                    }
+                }
+            }
+        }
+
+        public void Stop()
+        {
+            _isExitSignal = true;
+            WriteDebugInfo("Console stopped.");
+        }
+
+        public AbstractCommand GetCommand(string commandName)
+        {
+            return _commands.FirstOrDefault(x => x.Name.ToUpper() == commandName.ToUpper());            
+        }
+
+        public void AppendSelection(params ISelectionEntry[] selectionEntries)
+        {
+            if (selectionEntries == null)
+                throw new ArgumentNullException(nameof(selectionEntries));
+            foreach (var entry in selectionEntries)
+            {
+                _selections.Add(entry);
+            }
+            WriteDebugInfo($"{selectionEntries.Length} was added to global selections. Total count {_selections.Count} entries.");
+        }
+
+        public void ClearSelection()
+        {
+            _selections.Clear();
+            WriteDebugInfo("Global selections was cleared.");
+        }
+
+        public ISelectionEntry GetSelection(int ordinal)
+        {
+            if (ordinal==0)
+                throw new ArgumentOutOfRangeException(nameof(ordinal), "Ordinal value must be greater than 0.");
+            if (_selections.Count < ordinal)
+                throw new ArgumentOutOfRangeException(nameof(ordinal), $"Ordinal value must be less than {_selections.Count}.");
+
+            return _selections[ordinal - 1];
+        }
+         
+        #endregion
+
+        #region *** Public Operations ***
+        public void Dispose()
+        {
+            if (_isDispoising)
+                return;
+            _isDispoising = true;
+            WriteDebugInfo("Dispoising called.");
+            OnDispoising();
+            WriteDebugInfo("Dispoising done.");
+        }
+        #endregion
+
+        #region *** Protected Operations ***
+        protected virtual void OnDispoising()
+        {
+        }
+
+        protected virtual void OnShowHeader()
+        {
+            var headerText = string.IsNullOrEmpty(_configuration.ConsoleCopyright) ?  @"{0} * {1}" : @"{0} * {1} * {2}";
+            using (var writer = new ConsoleWriter(ConsoleColor.Green))
+            {
+                writer.WriteLine(!string.IsNullOrEmpty(_configuration.ConsoleCopyright)
+                    ? string.Format(headerText, _configuration.ConsoleName, _configuration.ConsoleVersion,
+                        _configuration.ConsoleCopyright)
+                    : string.Format(headerText, _configuration.ConsoleName, _configuration.ConsoleVersion));
+            }
+        }
+        #endregion
+
+        #region *** Private Operations ***
+        private static T Construct<T>(Type instance, Type[] paramTypes, object[] paramValues)
+        {            
+            var ci = instance.GetConstructor(
+                BindingFlags.Instance | BindingFlags.Public,
+                null, paramTypes, null);
+            if (ci == null)
+                throw new Exception($"Command class '{instance.FullName}' has not public constuctor defined or has bad constructor's format.");
+            return (T)ci.Invoke(paramValues);
+        }
+        private IEnumerable<Type> GetTypesWithHelpAttribute(Attribute attribute)
+        {
+           
+            WriteDebugInfo($"Loading command assemblies ...");
+
+            var defaultTypes = Assembly.GetExecutingAssembly().GetTypes().Where(type => type.GetCustomAttributes(attribute.GetType(), true).Length > 0).Distinct().ToList();
+            
+            var customTypes = new List<Type>();
+            if (_configuration.CommandDefinitionAssebmly != null)
+            {
+                foreach (var assembly in _configuration.CommandDefinitionAssebmly)
+                {
+                    customTypes.AddRange(assembly.GetTypes().Where(type => type.GetCustomAttributes(attribute.GetType(), true).Length > 0).Distinct().ToArray());
+                    WriteDebugInfo(assembly.GetName().Name + " was scanned for commands.");
+                }
+            }
+            else
+            {
+                WriteDebugInfo("Custom CommandDefinitionAssembly is not defined. Skip.");
+            }
+            WriteDebugInfo($"Command definition obtaining process found {defaultTypes.Count} default definitions and {customTypes.Count} custom definitions.");
+            defaultTypes.AddRange(customTypes);
+            defaultTypes = defaultTypes.Distinct().ToList();
+
+            foreach (var disabledCommand in _configuration.DisabledCommands)
+            {
+                var disabled = defaultTypes.FirstOrDefault(x => x.Name == disabledCommand);
+                if (disabled==null)
+                    continue;
+                defaultTypes.Remove(disabled);
+                WriteDebugInfo($"Commnad class '{disabled.Name}', fullname '{disabled.FullName}', assembly '{disabled.Assembly.GetName().Name}' was skipped by configuration.");
+            }
+
+            return defaultTypes.ToArray();
+        }
+
+        private void WriteDebugInfo(string text)
+        {
+            using (var debug = new DebugConsoleWriter())
+            {
+                debug.WriteDebugLine(text);
+            }
+        }
+
+        private void DumpException(ConsoleWriter writer, Exception e)
+        {
+            while (e != null)
+            {                                         
+                writer.WriteLine("- " + e.Message);
+                e = e.InnerException;
+            }
+        }
+
+
+        private void ShowHeader()
+        {
+            OnShowHeader();
+        }
+
+        #endregion
+    }
+}

+ 21 - 0
Common/qdr.fnd.core.qconsole/Extensions/AbstractArgumentExt.cs

@@ -0,0 +1,21 @@
+using Quadarax.Foundation.Core.QConsole.Argument;
+
+namespace Quadarax.Foundation.Core.QConsole.Extensions
+{
+    internal static class AbstractArgumentExt
+    {
+        internal static bool IsPositional(this AbstractArgument owner)
+        {
+            return owner.GetType().Name == nameof(OrdinalArgument);
+        }
+        internal static bool IsFlag(this AbstractArgument owner)
+        {
+            return owner.GetType().Name == nameof(FlagArgument);
+        }
+
+        internal static bool IsCodeAccessAllowed(this AbstractArgument owner)
+        {
+            return !IsPositional(owner) || ((OrdinalArgument) owner).IsCodeAllowed;
+        }
+    }
+}

+ 4 - 0
Common/qdr.fnd.core.qconsole/Handlers/General.cs

@@ -0,0 +1,4 @@
+namespace Quadarax.Foundation.Core.QConsole.Handlers
+{
+    public delegate void NothingToDo(Engine engine);
+}

+ 94 - 0
Common/qdr.fnd.core.qconsole/Value/AbstractValue.cs

@@ -0,0 +1,94 @@
+using System;
+
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public abstract class AbstractValue
+    {
+        private object _value;
+
+        /// <summary>
+        /// Defines if value is set. Not null.
+        /// </summary>
+        public bool HasValue => _value != null;
+
+        /// <summary>
+        /// Returns underlying system value type.
+        /// </summary>
+        public Type ValueType { get; }
+
+        public AbstractValue()
+        {
+            Reset();
+        }
+
+        public AbstractValue(Type valueType, object value) : this(valueType)
+        {
+            _value = value;
+        }
+        protected AbstractValue(Type valueType)
+        {
+            ValueType = valueType ?? throw new ArgumentNullException(nameof(valueType));
+        }
+
+        protected abstract object ConvertStringToValue(string valueAsString);
+
+        public abstract string AsString();
+
+        public void Set(string valueAsString)
+        {
+            if (string.IsNullOrEmpty(valueAsString))
+            {
+                Reset();
+                return;
+            }
+            Set(ConvertStringToValue(valueAsString));
+        }
+
+        public virtual void Set(object value)
+        {
+            _value = value;
+        }
+
+        public object Get()
+        {
+            return _value;
+        }
+
+        public void Reset()
+        {
+            _value = null;
+        }
+
+        public static AbstractValue Create(TypeValuesEnum typeValue)
+        {
+            switch (typeValue)
+            {
+                case TypeValuesEnum.Bool:
+                    return new BoolValue();
+                case TypeValuesEnum.Date:
+                    return new DateValue();
+                case TypeValuesEnum.DateTime:
+                    return new DateTimeValue();
+                case TypeValuesEnum.Decimal:
+                    return new DecimalValue();
+                case TypeValuesEnum.Guid:
+                    return new GuidValue();
+                case TypeValuesEnum.Integer:
+                    return new IntegerValue();
+                case TypeValuesEnum.String:
+                    return new StringValue();
+                case TypeValuesEnum.Time:
+                    return new TimeValue();
+                case TypeValuesEnum.TimeSpan:
+                    return new TimeSpanValue();
+                default:
+                    throw new NotSupportedException($"Unsupported argument value '{typeValue}'");
+            }
+        }
+
+        public override string ToString()
+        {
+            return AsString();
+        }
+    }
+}

+ 23 - 0
Common/qdr.fnd.core.qconsole/Value/BoolValue.cs

@@ -0,0 +1,23 @@
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public class BoolValue : AbstractValue
+    {
+        public BoolValue() : base()
+        {
+
+        }
+        public BoolValue(bool value) : base(typeof(bool), value)
+        {
+        }
+
+        protected override object ConvertStringToValue(string valueAsString)
+        {
+            return bool.Parse(valueAsString);
+        }
+
+        public override string AsString()
+        {
+            return HasValue ? Get().ToString() : string.Empty;
+        }
+    }
+}

+ 26 - 0
Common/qdr.fnd.core.qconsole/Value/DateTimeValue.cs

@@ -0,0 +1,26 @@
+using System;
+using System.Threading;
+
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public class DateTimeValue : DateValue
+    {
+
+        public DateTimeValue() : base()
+        {
+
+        }
+        public DateTimeValue(DateTime value, string dateTimeFormat) : base(value, dateTimeFormat)
+        {
+        }
+        public DateTimeValue(DateTime value) : base(value)
+        {
+            _dateformat = System.Threading.Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortDatePattern + " " +  System.Threading.Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortTimePattern;
+        }
+
+        public override string AsString()
+        {
+            return HasValue ? Get().ToString() : string.Empty;
+        }
+    }
+}

+ 34 - 0
Common/qdr.fnd.core.qconsole/Value/DateValue.cs

@@ -0,0 +1,34 @@
+using System;
+using System.Threading;
+
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public class DateValue : AbstractValue
+    {
+        protected string _dateformat;
+
+        public DateValue() : base()
+        {
+
+        }
+
+        public DateValue(DateTime value, string dateFormat) : base(typeof(DateTime), value)
+        {
+            _dateformat = dateFormat;
+        }
+        public DateValue(DateTime value) : base(typeof(DateTime), value)
+        {
+            _dateformat = System.Threading.Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortDatePattern;
+        }
+
+        protected override object ConvertStringToValue(string valueAsString)
+        {
+            return DateTime.Parse(valueAsString);
+        }
+
+        public override string AsString()
+        {
+            return HasValue ? ((DateTime)Get()).ToString(_dateformat) : string.Empty;
+        }
+    }
+}

+ 24 - 0
Common/qdr.fnd.core.qconsole/Value/DecimalValue.cs

@@ -0,0 +1,24 @@
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public class DecimalValue : AbstractValue
+    {
+        public DecimalValue() : base()
+        {
+
+        }
+
+        public DecimalValue(decimal value) : base(typeof(decimal), value)
+        {
+        }
+
+        protected override object ConvertStringToValue(string valueAsString)
+        {
+            return decimal.Parse(valueAsString);
+        }
+
+        public override string AsString()
+        {
+            return HasValue ? Get().ToString() : string.Empty;
+        }
+    }
+}

+ 26 - 0
Common/qdr.fnd.core.qconsole/Value/GuidValue.cs

@@ -0,0 +1,26 @@
+using System;
+
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public class GuidValue : AbstractValue
+    {
+        public GuidValue() : base()
+        {
+
+        }
+
+        public GuidValue(Guid value) : base(typeof(Guid), value)
+        {
+        }
+
+        protected override object ConvertStringToValue(string valueAsString)
+        {
+            return valueAsString;
+        }
+
+        public override string AsString()
+        {
+            return HasValue ? Get().ToString() : string.Empty;
+        }
+    }
+}

+ 25 - 0
Common/qdr.fnd.core.qconsole/Value/IntegerValue.cs

@@ -0,0 +1,25 @@
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public class IntegerValue : AbstractValue
+    {
+
+        public IntegerValue() : base()
+        {
+
+        }
+
+        public IntegerValue(int value) : base(typeof(int), value)
+        {
+        }
+
+        protected override object ConvertStringToValue(string valueAsString)
+        {
+            return int.Parse(valueAsString);
+        }
+
+        public override string AsString()
+        {
+            return HasValue ? Get().ToString() : string.Empty;
+        }
+    }
+}

+ 26 - 0
Common/qdr.fnd.core.qconsole/Value/StringValue.cs

@@ -0,0 +1,26 @@
+using System;
+
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public class StringValue : AbstractValue
+    {
+        public StringValue() : base()
+        {
+
+        }
+
+        public StringValue(Type valueType, object value) : base(valueType, value)
+        {
+        }
+
+        protected override object ConvertStringToValue(string valueAsString)
+        {
+            return valueAsString;
+        }
+
+        public override string AsString()
+        {
+            return HasValue ? Get().ToString() : string.Empty;
+        }
+    }
+}

+ 18 - 0
Common/qdr.fnd.core.qconsole/Value/TimeSpanValue.cs

@@ -0,0 +1,18 @@
+using System;
+
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public class TimeSpanValue : AbstractValue
+    {
+
+        protected override object ConvertStringToValue(string valueAsString)
+        {
+            return TimeSpan.Parse(valueAsString);
+        }
+
+        public override string AsString()
+        {
+            return HasValue ? Get().ToString() : string.Empty;
+        }
+    }
+}

+ 22 - 0
Common/qdr.fnd.core.qconsole/Value/TimeValue.cs

@@ -0,0 +1,22 @@
+using System;
+
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public class TimeValue : DateValue
+    {
+
+        public TimeValue() : base()
+        {
+
+        }
+
+        public TimeValue(DateTime value, string timeFormat) : base(value, timeFormat)
+        {
+        }
+
+        public TimeValue(DateTime value) : base(value)
+        {
+            _dateformat = System.Threading.Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortTimePattern;
+        }
+    }
+}

+ 15 - 0
Common/qdr.fnd.core.qconsole/Value/TypeValuesEnum.cs

@@ -0,0 +1,15 @@
+namespace Quadarax.Foundation.Core.QConsole.Value
+{
+    public enum TypeValuesEnum
+    {
+        Bool,
+        DateTime,
+        Date,
+        Decimal,
+        Guid,
+        Integer,
+        String,
+        Time,
+        TimeSpan,
+    }
+}

+ 18 - 0
Common/qdr.fnd.core.qconsole/qdr.fnd.core.qconsole.csproj

@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>..\bo_strong_key_pair.snk</AssemblyOriginatorKeyFile>
+    <DelaySign>false</DelaySign>
+    <RootNamespace>Quadarax.Foundation.Core.QConsole</RootNamespace>
+    <ApplicationIcon>..\quadarax_dll.ico</ApplicationIcon>
+    <AssemblyVersion>1.0.6.0</AssemblyVersion>
+    <FileVersion>1.0.6.0</FileVersion>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\qdr.fnd.core\qdr.fnd.core.csproj" />
+  </ItemGroup>
+
+</Project>

+ 90 - 0
Common/qdr.fnd.core.web/Controllers/BaseController.cs

@@ -0,0 +1,90 @@
+using System;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using Quadarax.Foundation.Core.Business.Interface;
+using Quadarax.Foundation.Core.Data.Interface.Entity.Dto;
+
+namespace Quadarax.Foundation.Core.Web.Controllers
+{
+    public abstract class BaseController<TController, TService>  : ControllerBase 
+        where TController : ControllerBase
+        where TService : IService 
+    {
+        private ILogger<TController> _logger;
+
+        protected TService Service { get; }
+
+        protected BaseController(ILoggerFactory logger, TService service)
+        {
+            _logger = logger.CreateLogger<TController>() ?? throw new ArgumentNullException(nameof(logger));
+            Service = service ?? throw new ArgumentNullException(nameof(service));
+        }
+
+        protected void ProcessException(ResultDto result, Exception exception)
+        {
+
+        }
+        
+        [HttpGet("test")]
+        public ResultPlain Test()
+        {
+            return Call(() => 
+                (ResultPlain)Service.Test()
+            );
+        }
+
+        public  TResult Call<TResult>(Func<TResult> block) where TResult : ResultDto, new()
+        {
+            var result = new TResult();
+            try
+            {
+                return block();
+            }
+            catch (Exception e)
+            {
+                ProcessException(result, e);
+            }
+
+            return result;
+        }
+
+        protected void LogInfo(string message)
+        {
+            _logger.Log(LogLevel.Information, message);
+        }
+
+        protected void LogDebug(string message)
+        {
+            _logger.Log(LogLevel.Debug, message);
+        }
+        protected void LogTrace(string message)
+        {
+            _logger.Log(LogLevel.Trace, message);
+        }
+        protected void LogWarn(string message)
+        {
+            _logger.Log(LogLevel.Warning, message);
+        }
+        protected void LogWarn(string message, Exception exception)
+        {
+            _logger.Log(LogLevel.Warning, message);
+        } 
+        protected void LogWarn(Exception exception)
+        {
+            _logger.Log(LogLevel.Warning, exception.ToString());
+        }
+        protected void LogError(string message)
+        {
+            _logger.Log(LogLevel.Error, message);
+        }
+        protected void LogError(string message, Exception exception)
+        {
+            _logger.Log(LogLevel.Error, message);
+        } 
+        protected void LogError(Exception exception)
+        {
+            _logger.Log(LogLevel.Error, exception.ToString());
+        }
+
+    }
+}

+ 23 - 0
Common/qdr.fnd.core.web/Extensions/DtoExt.cs

@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+using Quadarax.Foundation.Core.Data.Interface.Entity.Dto;
+
+namespace Quadarax.Foundation.Core.Web.Extensions
+{
+    public static class DtoExt
+    {
+        public static ResultValueDto<TDto> AsResult<TDto>(this TDto value) where TDto : IDto, new()
+        {
+            if (value==null)
+                throw new ArgumentNullException(nameof(value));
+            return new ResultValueDto<TDto>(value);
+        }
+        public static ResultsValueDto<TDto> AsResult<TDto>(this IEnumerable<TDto> values) where TDto : IDto
+        {
+            if (values==null)
+                throw new ArgumentNullException(nameof(values));
+            return new ResultsValueDto<TDto>(values);
+        }
+    }
+}

+ 28 - 0
Common/qdr.fnd.core.web/Logging/AutoLogAttribute.cs

@@ -0,0 +1,28 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+
+namespace Quadarax.Foundation.Core.Web.Logging
+{
+    public class AutoLogAttribute : TypeFilterAttribute
+    {
+        public AutoLogAttribute() : base(typeof(AutoLogActionFilterImpl))
+        {
+        }
+
+        private class AutoLogActionFilterImpl : IActionFilter
+        {
+            public AutoLogActionFilterImpl()
+            {
+            }
+
+            public void OnActionExecuting(ActionExecutingContext context)
+            {
+            }
+
+            public void OnActionExecuted(ActionExecutedContext context)
+            {
+                //this.LogInfo($"RQ[{context.HttpContext.Request.Method}]: {context.HttpContext.Request.Path}"); 
+            }
+        }
+    }
+}

+ 22 - 0
Common/qdr.fnd.core.web/qdr.fnd.core.web.csproj

@@ -0,0 +1,22 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <SignAssembly>true</SignAssembly>
+    <AssemblyOriginatorKeyFile>..\bo_strong_key_pair.snk</AssemblyOriginatorKeyFile>
+    <DelaySign>false</DelaySign>
+    <RootNamespace>Quadarax.Foundation.Core.Web</RootNamespace>
+    <ApplicationIcon>..\quadarax_dll.ico</ApplicationIcon>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
+    <PackageReference Include="NLog" Version="5.0.4" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\qdr.fnd.core.business\qdr.fnd.core.business.csproj" />
+    <ProjectReference Include="..\qdr.fnd.core\qdr.fnd.core.csproj" />
+  </ItemGroup>
+
+</Project>

+ 6 - 0
Common/qdr.fnd.core/Api/IApiClient.cs

@@ -0,0 +1,6 @@
+namespace Quadarax.Foundation.Core.Api
+{
+    public interface IApiClient
+    {
+    }
+}

+ 23 - 0
Common/qdr.fnd.core/Attributes/DiImplementsOfAttribute.cs

@@ -0,0 +1,23 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Attributes
+{
+    [AttributeUsage(AttributeTargets.Class,AllowMultiple = true)]
+    public class DiImplementsOfAttribute : Attribute
+    {
+
+        public Type InterfaceTypeImplementing { get; }
+        public LifeCycleTypeEnum LifeCycleType { get; }
+
+        public DiImplementsOfAttribute(Type interfaceType, LifeCycleTypeEnum lifeCycleType)
+
+        {
+            if (interfaceType == null)
+                throw new ArgumentNullException(nameof(interfaceType));
+            if (!interfaceType.IsInterface)
+                throw new ArgumentException("DiImplementsOf expects interface type", nameof(interfaceType));
+            LifeCycleType = lifeCycleType;
+            InterfaceTypeImplementing = interfaceType;
+        }
+    }
+}

+ 9 - 0
Common/qdr.fnd.core/Attributes/DiModuleAttribute.cs

@@ -0,0 +1,9 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Attributes
+{
+    [AttributeUsage(validOn:AttributeTargets.Class)]
+    public class DiModuleAttribute : Attribute
+    {
+    }
+}

+ 9 - 0
Common/qdr.fnd.core/Attributes/LifeCycleTypeEnum.cs

@@ -0,0 +1,9 @@
+namespace Quadarax.Foundation.Core.Attributes
+{
+    public enum LifeCycleTypeEnum
+    {
+        Singleton,
+        Scoped,
+        Transient
+    }
+}

+ 84 - 0
Common/qdr.fnd.core/Console/ConsoleWriter.cs

@@ -0,0 +1,84 @@
+using System;
+using Quadarax.Foundation.Core.Object;
+
+namespace Quadarax.Foundation.Core.Console
+{
+    public class ConsoleWriter : DisposableObject
+    {
+        private readonly ConsoleColor _oldBackColor;
+        private readonly ConsoleColor _oldForeColor;
+        private readonly ConsoleColor _backColor;
+        private readonly ConsoleColor _foreColor;
+
+
+        public ConsoleWriter(ConsoleColor foreColor,ConsoleColor backColor)
+        {
+            _oldBackColor = System.Console.BackgroundColor;
+            _oldForeColor = System.Console.ForegroundColor;
+            _backColor = backColor;
+            _foreColor = foreColor;
+        }
+
+        public ConsoleWriter(ConsoleColor foreColor)
+        {
+            _oldBackColor = System.Console.BackgroundColor;
+            _oldForeColor = System.Console.ForegroundColor;
+            _backColor = _oldBackColor;
+            _foreColor = foreColor;
+        }
+
+
+        public ConsoleWriter WriteLine(string text)
+        {
+            SetColor();
+            WriteInternal(text);
+            WriteLineInternal();
+            return this;
+        }
+
+        public string ReadLine()
+        {
+            SetColor();
+            return System.Console.ReadLine();
+        }
+
+        public ConsoleWriter WriteLine()
+        {
+            WriteLineInternal();
+            return this;
+        }
+        public ConsoleWriter Write(string text)
+        {
+            SetColor();
+            WriteInternal(text);
+            return this;
+        }
+
+        public static void Clear()
+        {
+            System.Console.Clear();
+        }
+
+        protected virtual void WriteInternal(string text)
+        {
+            System.Console.Write(text);
+        }
+        protected virtual void WriteLineInternal()
+        {
+            System.Console.WriteLine();
+        }
+
+        protected override void OnDisposing()
+        {
+            System.Console.ForegroundColor = _oldForeColor;
+            System.Console.BackgroundColor = _oldBackColor;
+        }
+
+        private void SetColor()
+        {
+            System.Console.ForegroundColor = _foreColor;
+            System.Console.BackgroundColor = _backColor;
+        }
+
+    }
+}

+ 113 - 0
Common/qdr.fnd.core/Console/ProgressBar.cs

@@ -0,0 +1,113 @@
+using System;
+using System.Text;
+using System.Threading;
+using Quadarax.Foundation.Core.Object;
+// ReSharper disable InconsistentNaming
+
+namespace Quadarax.Foundation.Core.Console
+{
+    public class ProgressBar : DisposableObject, IProgress<double>
+    {
+
+        #region *** Constants ***
+        private const int CN_BLOCK_COUNT = 10;
+        private const string CS_ANIMATION = @"|/-\";
+        #endregion
+        #region *** Private fields ***
+        private readonly TimeSpan _animationInterval = TimeSpan.FromSeconds(1.0 / 8);
+        private readonly Timer _timer;
+        private double _currentProgress;
+        private string _currentText = string.Empty;
+        private int _animationIndex;
+        private ConsoleWriter _writer;
+        #endregion
+
+        #region *** Constructors ***
+        public ProgressBar(ConsoleWriter writer)
+        {
+            _writer = writer ?? throw new ArgumentNullException(nameof(writer));
+            _timer = new Timer(TimerHandler);
+
+            // A progress bar is only for temporary display in a console window.
+            // If the console output is redirected to a file, draw nothing.
+            // Otherwise, we'll end up with a lot of garbage in the target file.
+            if (!System.Console.IsOutputRedirected)
+            {
+                ResetTimer();
+            }
+        }
+        #endregion
+
+        #region *** Public Operations ***
+        /// <summary>
+        /// Update progress status.
+        /// </summary>
+        /// <param name="value">Status value between 0 - 1. Represents percentage.</param>
+        public void Report(double value)
+        {
+            // Make sure value is in [0..1] range
+            value = Math.Max(0, Math.Min(1, value));
+            Interlocked.Exchange(ref _currentProgress, value);
+        }
+        #endregion
+
+        #region *** Private Operations ***
+        private void TimerHandler(object state)
+        {
+            lock (_timer)
+            {
+                var progressBlockCount = (int)(_currentProgress * CN_BLOCK_COUNT);
+                var percent = (int)(_currentProgress * 100);
+                var text = $"[{new string('#', progressBlockCount)}{new string('-', CN_BLOCK_COUNT - progressBlockCount)}] {percent,3}% {CS_ANIMATION[_animationIndex++ % CS_ANIMATION.Length]}";
+                UpdateText(text);
+                ResetTimer();
+            }
+        }
+
+        private void UpdateText(string text)
+        {
+            // Get length of common portion
+            var commonPrefixLength = 0;
+            var commonLength = Math.Min(_currentText.Length, text.Length);
+            while (commonPrefixLength < commonLength && text[commonPrefixLength] == _currentText[commonPrefixLength])
+            {
+                commonPrefixLength++;
+            }
+
+            // Backtrack to the first differing character
+            var outputBuilder = new StringBuilder();
+            outputBuilder.Append('\b', _currentText.Length - commonPrefixLength);
+
+            // Output new suffix
+            outputBuilder.Append(text.Substring(commonPrefixLength));
+
+            // If the new text is shorter than the old one: delete overlapping characters
+            var overlapCount = _currentText.Length - text.Length;
+            if (overlapCount > 0)
+            {
+                outputBuilder.Append(' ', overlapCount);
+                outputBuilder.Append('\b', overlapCount);
+            }
+
+            _writer.Write(outputBuilder.ToString());
+            _currentText = text;
+        }
+
+        private void ResetTimer()
+        {
+            _timer.Change(_animationInterval, TimeSpan.FromMilliseconds(-1));
+        }
+        #endregion
+
+        #region *** Private Overrides ***
+        protected override void OnDisposing()
+        {
+            lock (_timer)
+            {
+                UpdateText(string.Empty);
+                _writer = null;
+            }
+        }
+        #endregion
+    }
+}

+ 78 - 0
Common/qdr.fnd.core/Console/ProgressConsoleWriter.cs

@@ -0,0 +1,78 @@
+using System;
+using System.Text;
+
+namespace Quadarax.Foundation.Core.Console
+{
+    public class ProgressConsoleWriter : ConsoleWriter
+    {
+        #region *** Private Fields ***
+        private int _maxProgress;
+        private int _curProgress = 0;
+        private string _lastText;
+        #endregion
+
+        #region *** Constructors ***
+        public ProgressConsoleWriter(ConsoleColor foreColor, ConsoleColor backColor, int maxProgress) : base(foreColor, backColor)
+        {
+            _maxProgress = maxProgress;
+        }
+
+        public ProgressConsoleWriter(ConsoleColor foreColor, int maxProgress) : base(foreColor)
+        {
+            _maxProgress = maxProgress;
+        }
+        #endregion
+
+        #region *** Public Operations ***
+
+        public void SetProgress(int progress)
+        {
+            _curProgress = progress;
+            OnRefreshProgress();
+        }
+        public void IncProgress()
+        {
+            _curProgress++;
+            OnRefreshProgress();
+        }
+        public void DecProgress()
+        {
+            _curProgress--;
+            OnRefreshProgress();
+        }
+        
+        #endregion
+
+        #region *** Internal Operations ***
+
+        protected override void WriteLineInternal()
+        {
+            base.WriteLineInternal();
+            OnRefreshProgress();
+        }
+
+        protected override void WriteInternal(string text)
+        {
+            _lastText = text;
+            OnRefreshProgress();
+        }
+
+        private void OnRefreshProgress()
+        {
+            base.WriteInternal("\r");
+            base.WriteInternal(new string(' ', System.Console.BufferWidth - 1));
+            base.WriteInternal("\r");
+            var sb = new StringBuilder();
+            sb.Append("[").Append(_curProgress).Append("/").Append(_maxProgress).Append("] ").Append(_lastText);
+            base.WriteInternal(sb.ToString());
+        }
+        protected override void OnDisposing()
+        {
+            System.Console.WriteLine();
+            base.OnDisposing();
+        }
+
+        #endregion
+
+    }
+}

+ 44 - 0
Common/qdr.fnd.core/Data/CsvHelper.cs

@@ -0,0 +1,44 @@
+using System;
+using System.Data;
+using System.IO;
+
+namespace Quadarax.Foundation.Core.Data
+{
+    public static class CsvHelper
+    {
+        /// <summary>
+        /// Read CSV file and creates <see cref="DataTable"/> with filled content.
+        /// <remarks>
+        /// This method expects first header row.
+        /// </remarks>
+        /// </summary>
+        /// <param name="csvFile">(*.csv) full file name.</param>
+        /// <param name="delimiter">Delimiter character</param>
+        /// <returns>New created DataTable with content.</returns>
+        public static DataTable CsvToDataTable(string csvFile, string delimiter)
+        {
+            var dt = new DataTable();
+            using (var sr = new StreamReader(csvFile))
+            {
+                var headers = sr.ReadLine().Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
+                foreach (var header in headers)
+                {
+                    dt.Columns.Add(header);
+                }
+
+                while (!sr.EndOfStream)
+                {
+                    var rows = sr.ReadLine().Split(new[] { delimiter }, StringSplitOptions.None);
+                    var dr = dt.NewRow();
+                    for (var i = 0; i < headers.Length; i++)
+                    {
+                        dr[i] = rows[i];
+                    }
+
+                    dt.Rows.Add(dr);
+                }
+            }
+            return dt;
+        }
+    }
+}

Some files were not shown because too many files changed in this diff