ソースを参照

add Worbench project and add Processor prototype (not finished)

Dalibor Votruba 2 年 前
コミット
0ea0f44724
26 ファイル変更911 行追加0 行削除
  1. 29 0
      Common/qdr.fnd.core/Value/TypedArgument.cs
  2. 12 0
      Workbench/Processor/Dependencies/Logging/ILog.cs
  3. 9 0
      Workbench/Processor/Dependencies/Logging/ILogHandler.cs
  4. 10 0
      Workbench/Processor/Dependencies/Logging/ILogger.cs
  5. 12 0
      Workbench/Processor/Dependencies/Logging/LogSeverityEnum.cs
  6. 19 0
      Workbench/Processor/Dependencies/Object/DisposableObject.cs
  7. 44 0
      Workbench/Processor/Dependencies/Object/Extensions/ObjectExt.cs
  8. 71 0
      Workbench/Processor/Dependencies/Object/Singleton.cs
  9. 32 0
      Workbench/Processor/Dependencies/Object/WeakReference.cs
  10. 75 0
      Workbench/Processor/Dependencies/Reflection/AttributeQuery.cs
  11. 31 0
      Workbench/Processor/Dependencies/Reflection/Extensions/ActivatorExt.cs
  12. 73 0
      Workbench/Processor/Dependencies/Reflection/Extensions/AssemblyExt.cs
  13. 26 0
      Workbench/Processor/Dependencies/Reflection/Extensions/AssemblyNameExt.cs
  14. 37 0
      Workbench/Processor/Dependencies/Reflection/Extensions/TypeExt.cs
  15. 119 0
      Workbench/Processor/Dependencies/Reflection/QualifiedName.cs
  16. 51 0
      Workbench/Processor/Dependencies/Reflection/TypeUtils.cs
  17. 9 0
      Workbench/Processor/Enums/ProcessQueueTypeEnum.cs
  18. 16 0
      Workbench/Processor/Enums/ProcessStatusEnum.cs
  19. 15 0
      Workbench/Processor/Processor.csproj
  20. 25 0
      Workbench/Processor/Processor.sln
  21. 2 0
      Workbench/Processor/Program.cs
  22. 71 0
      Workbench/Processor/Task/AffinityToken.cs
  23. 25 0
      Workbench/Processor/Task/IAffinityToken.cs
  24. 15 0
      Workbench/Processor/Task/ITaskIdentifier.cs
  25. 68 0
      Workbench/Processor/Task/ITaskItem.cs
  26. 15 0
      Workbench/Processor/Task/ITimeTracked.cs

+ 29 - 0
Common/qdr.fnd.core/Value/TypedArgument.cs

@@ -0,0 +1,29 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Value;
+
+public class TypedArgument
+{
+    public string Name {get; private set;}
+    public string Value {get; private set;}  //TODO: must be nullable
+    public Type ValueType {get; private set;}
+       
+    public bool IsOutput {get; private set;}
+       
+    public TypedArgument(string name, string valueAsString, Type valueType, bool isOutput = false)
+    {
+        Name = name ?? throw new ArgumentNullException(nameof(name));
+        ValueType = valueType ?? throw new ArgumentNullException(nameof(valueType));
+        Value = valueAsString;
+        IsOutput = isOutput;
+    }
+    public TypedArgument(string name, Type valueType, bool isOutput = false) : this(name, string.Empty, valueType, isOutput)
+    {
+         
+    }
+    public TypedArgument(string name, object valueTyped, bool isOutput = false) : this(name, valueTyped?.ToString(), valueTyped?.GetType(), isOutput)
+    {
+         
+    }  
+}
+   

+ 12 - 0
Workbench/Processor/Dependencies/Logging/ILog.cs

@@ -0,0 +1,12 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Logging
+{
+    public interface ILog
+    {
+        void Log(LogSeverityEnum severity, int code, string message);
+        void Log(LogSeverityEnum severity, string message);
+        void Log(LogSeverityEnum severity, string message, Exception exception);
+        void Log(LogSeverityEnum severity, int code, string message, Exception exception);
+    }
+}

+ 9 - 0
Workbench/Processor/Dependencies/Logging/ILogHandler.cs

@@ -0,0 +1,9 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Logging
+{
+    public interface ILogHandler
+    {
+        void Log(LogSeverityEnum type, string message, Exception e = null);
+    }
+}

+ 10 - 0
Workbench/Processor/Dependencies/Logging/ILogger.cs

@@ -0,0 +1,10 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Logging
+{
+    public interface ILogger
+    {
+        ILog GetLogger(string loggerName);
+        ILog GetLogger(Type loggerForType);
+    }
+}

+ 12 - 0
Workbench/Processor/Dependencies/Logging/LogSeverityEnum.cs

@@ -0,0 +1,12 @@
+namespace Quadarax.Foundation.Core.Logging
+{
+    public enum LogSeverityEnum
+    {
+        Trace,
+        Debug,
+        Info,
+        Warn,
+        Error,
+        Fatal
+    }
+}

+ 19 - 0
Workbench/Processor/Dependencies/Object/DisposableObject.cs

@@ -0,0 +1,19 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Object
+{
+    public abstract class DisposableObject : IDisposable
+    {
+        private bool _isDisposing;
+
+        public void Dispose()
+        {
+            if (_isDisposing)
+                return;
+            _isDisposing = true;
+            OnDisposing();
+        }
+
+        protected abstract void OnDisposing();
+    }
+}

+ 44 - 0
Workbench/Processor/Dependencies/Object/Extensions/ObjectExt.cs

@@ -0,0 +1,44 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Quadarax.Foundation.Core.Reflection.Extensions;
+
+namespace Quadarax.Foundation.Core.Object.Extensions
+{
+    public static class ObjectExt
+    {
+        public static IDictionary<string, object> GetAllPropertyValues(this object obj,string indentPrefix = null)
+        {
+            var props = new Dictionary<string, object>();
+            if (obj == null)
+                return props;
+
+            if (string.IsNullOrEmpty(indentPrefix))
+                indentPrefix = string.Empty;
+
+            var type = obj.GetType();
+            var propList = type.GetAllProperties();
+            foreach (var prop in propList)
+            {
+                var val = prop.GetValue(obj, new object[] { });
+                if (val is IEnumerable enumerable)
+                {
+                    var cnt = 0;
+                    foreach (var item in enumerable)
+                    {
+                        var itemProps = item.GetAllPropertyValues(prop.Name + $"[{cnt}].");
+                        foreach (var ip in itemProps)
+                            props.Add(ip.Key, ip.Value);
+                        cnt++;
+                    }
+                }
+                else
+                    props.Add(indentPrefix + prop.Name, val);
+            }
+ 
+            return props;
+        }
+
+    }
+}

+ 71 - 0
Workbench/Processor/Dependencies/Object/Singleton.cs

@@ -0,0 +1,71 @@
+namespace Quadarax.Foundation.Core.Object
+{
+  
+        /// <summary>
+        /// Well-known singleton pattern implementation.
+        /// </summary>
+        /// <remarks>
+        /// The singleton type must inherit this class. The actual instance type is determined
+        /// by the only type parameter. The singleton type must implement a default constructor.
+        /// </remarks>
+        /// <typeparam name="TInstance"></typeparam>
+        public class Singleton<TInstance> where TInstance : new()
+        {
+            private static TInstance _instance;
+            private static readonly object _syncRoot = new object();
+
+            /// <summary>
+            /// Singleton instance
+            /// </summary>
+            public static TInstance Instance
+            {
+                get
+                {
+                    if (_instance == null)
+                    {
+                        lock (_syncRoot)
+                        {
+                            if (_instance == null)
+                                _instance = new TInstance();
+                        }
+                    }
+
+                    return _instance;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Well-known singleton pattern implementation.
+        /// </summary>
+        /// <remarks>
+        /// The singleton type must inherit this class. The actual instance type is determined
+        /// by the only type parameter. The singleton type must implement a default constructor.
+        /// </remarks>
+        /// <typeparam name="TInstance"></typeparam>
+        /// <typeparam name="TInterface"></typeparam>
+        public class Singleton<TInterface, TInstance>
+            where TInstance : TInterface, new()
+            where TInterface : class
+        {
+            private static volatile TInterface _instance;
+            private static readonly object _syncRoot = new object();
+
+            public static TInterface Instance
+            {
+                get
+                {
+                    if (_instance == null)
+                    {
+                        lock (_syncRoot)
+                        {
+                            if (_instance == null)
+                                _instance = new TInstance();
+                        }
+                    }
+
+                    return _instance;
+                }
+            }
+        }
+}

+ 32 - 0
Workbench/Processor/Dependencies/Object/WeakReference.cs

@@ -0,0 +1,32 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Object
+{
+    /// <summary>
+    /// Strongly typed version of <see cref="WeakReference"/>.
+    /// </summary>
+    /// <typeparam name="TReference"></typeparam>
+    public class WeakReference<TReference> : WeakReference 
+        where TReference : class
+    {
+        public WeakReference(TReference target)
+            : base(target)
+        {
+        }
+
+        public WeakReference(TReference target, bool trackResurrection)
+            : base(target, trackResurrection)
+        {
+        }
+
+        /// <summary>
+        /// Strongly typed version of <see cref="WeakReference.Target"/>.
+        /// </summary>
+        public new TReference Target
+        {
+            get { return base.Target as TReference; }
+            set { base.Target = value; }
+        }
+    }
+
+}

+ 75 - 0
Workbench/Processor/Dependencies/Reflection/AttributeQuery.cs

@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Quadarax.Foundation.Core.Reflection
+{
+    public static class AttributeQuery<TAttributeType> where TAttributeType : Attribute
+    {
+        public static TAttributeType Get<TAttributeProvider>(TAttributeProvider oProvider)
+            where TAttributeProvider : ICustomAttributeProvider
+        {
+            return Get(oProvider, true);
+        }
+
+        public static TAttributeType Get<TAttributeProvider>(TAttributeProvider oProvider, bool bInherit)
+            where TAttributeProvider : ICustomAttributeProvider
+        {
+            TAttributeType attribute = Find(oProvider, bInherit);
+            if (attribute == null)
+            {
+                throw new Exception($"Cannot find attribute '{typeof(TAttributeType).Name}' inside class '{oProvider.GetType().AssemblyQualifiedName}'");
+            }
+            return attribute;
+        }
+
+        public static TAttributeType Find<TAttributeProvider>(TAttributeProvider oProvider, bool bInherit)
+            where TAttributeProvider : ICustomAttributeProvider
+        {
+            TAttributeType[] attributes = FindAll(oProvider, bInherit);
+            return attributes.Length > 0 ? attributes[0] : null;
+        }
+
+        public static TAttributeType[] FindAll<TAttributeProvider>(TAttributeProvider oProvider)
+            where TAttributeProvider : ICustomAttributeProvider
+        {
+            return FindAll(oProvider, true);
+        }
+
+        public static TAttributeType[] FindAll<TAttributeProvider>(TAttributeProvider oProvider, bool bInherit)
+            where TAttributeProvider : ICustomAttributeProvider
+        {
+            return (TAttributeType[])oProvider.GetCustomAttributes(typeof(TAttributeType), bInherit);
+        }
+
+        public static MemberInfo[] GetMembers(Type oSource, BindingFlags eFlags)
+        {
+            var oResult = new List<MemberInfo>();
+            if (oSource.IsEnum)
+            {
+                var oMembers = oSource.GetEnumValues();
+                foreach (var oMember in oMembers)
+                {
+                    var oMemberInfo = oSource.GetMember(oMember.ToString() ?? string.Empty);                                        
+                    if (Has(oMemberInfo[0]))
+                        oResult.Add(oMemberInfo[0]);                    
+                }
+                return oResult.ToArray();
+            }
+            throw new NotSupportedException(
+                $"Attribute query in GetMembers does't support type object '{oSource.AssemblyQualifiedName}");
+        }
+
+        public static bool Has<TAttributeProvider>(TAttributeProvider oProvider)
+            where TAttributeProvider : ICustomAttributeProvider
+        {
+            return oProvider.IsDefined(typeof(TAttributeType), true);
+        }
+
+        public static bool Has<TAttributeProvider>(TAttributeProvider oProvider, bool bInherit)
+            where TAttributeProvider : ICustomAttributeProvider
+        {
+            return Find(oProvider, bInherit) != null;
+        }
+    }
+}

+ 31 - 0
Workbench/Processor/Dependencies/Reflection/Extensions/ActivatorExt.cs

@@ -0,0 +1,31 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Reflection.Extensions
+{
+    public static class ActivatorExt
+    {
+        #region *** Private Fields ***
+        #endregion
+        #region *** Public Properties ***
+        #endregion
+        #region *** Constructors ***
+        #endregion
+        #region *** Public operations & overrides ***
+        public static object CreateInstance(string sClassOrInterfaceQualifiedName, bool bLoadAssemblyIfNeeded, params object[] aConstructorParams)
+        {
+            var oType = Type.GetType(sClassOrInterfaceQualifiedName, false) ?? TypeUtils.GetRemoteType(sClassOrInterfaceQualifiedName);
+            if (oType.IsInterface)
+            {
+                throw new ArgumentException($"Input class name '{sClassOrInterfaceQualifiedName}' cannot be an interface.",nameof(sClassOrInterfaceQualifiedName));
+            }
+            return Activator.CreateInstance(oType, aConstructorParams);
+        }
+        public static T CreateInstance<T>(string sClassOrInterfaceQualifiedName, bool bLoadAssemblyIfNeeded, params object[] aConstructorParams)
+        {
+            return (T) CreateInstance(sClassOrInterfaceQualifiedName, bLoadAssemblyIfNeeded, aConstructorParams);
+        }
+        #endregion
+        #region *** Private operations & overrides ***
+        #endregion        
+    }
+}

+ 73 - 0
Workbench/Processor/Dependencies/Reflection/Extensions/AssemblyExt.cs

@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+
+namespace Quadarax.Foundation.Core.Reflection.Extensions
+{
+    public static class AssemblyExt
+    {
+        #region *** Private Fields ***
+        #endregion
+        #region *** Public Properties ***
+        #endregion
+        #region *** Constructors ***
+        #endregion
+        #region *** Public operations & overrides ***
+        public static Version GetVersion(this Assembly oAssembly)
+        {
+            return oAssembly.GetName().Version;
+        }
+        public static string GetDescription(this Assembly oAssembly)
+        {
+            var oAttribute = oAssembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), true).FirstOrDefault();
+            if (oAttribute == null)
+                return string.Empty;
+            return ((AssemblyDescriptionAttribute)oAttribute).Description;
+        }
+        public static string GetProduct(this Assembly oAssembly)
+        {
+            var oAttribute = oAssembly.GetCustomAttributes(typeof(AssemblyProductAttribute), true).FirstOrDefault();
+            if (oAttribute == null)
+                return string.Empty;
+            return ((AssemblyProductAttribute)oAttribute).Product;
+        }
+        public static string GetCompany(this Assembly oAssembly)
+        {
+            var oAttribute = oAssembly.GetCustomAttributes(typeof(AssemblyCompanyAttribute), true).FirstOrDefault();
+            if (oAttribute == null)
+                return string.Empty;
+            return ((AssemblyCompanyAttribute)oAttribute).Company;
+        }
+        public static string GetCopyright(this Assembly oAssembly)
+        {
+            var oAttribute = oAssembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), true).FirstOrDefault();
+            if (oAttribute == null)
+                return string.Empty;
+            return ((AssemblyCopyrightAttribute)oAttribute).Copyright;
+        }
+        public static string GetTrademark(this Assembly oAssembly)
+        {
+            var oAttribute = oAssembly.GetCustomAttributes(typeof(AssemblyTrademarkAttribute), true).FirstOrDefault();
+            if (oAttribute == null)
+                return string.Empty;
+            return ((AssemblyTrademarkAttribute)oAttribute).Trademark;
+        }
+        public static string GetAssemblyPath(this Assembly oAssembly)
+        {
+            return Path.GetDirectoryName(new Uri(oAssembly.CodeBase).LocalPath) + Path.DirectorySeparatorChar;
+        }
+        public static IEnumerable<Type> GetTypesWithAttribute<TAttribute>(this Assembly oAssembly, bool bInherit)where TAttribute : System.Attribute
+        {
+            var types = oAssembly.GetTypes();
+            return types.Where(x => x.IsDefined(typeof(TAttribute), bInherit)).ToArray();
+        }
+
+        #endregion
+        #region *** Private operations & overrides ***
+        #endregion
+
+
+    }
+}

+ 26 - 0
Workbench/Processor/Dependencies/Reflection/Extensions/AssemblyNameExt.cs

@@ -0,0 +1,26 @@
+using System.Reflection;
+using System.Text;
+
+namespace Quadarax.Foundation.Core.Reflection.Extensions
+{
+    public static class AssemblyNameExt
+    {
+        #region *** Private Fields ***
+		#endregion
+		
+		#region *** Public operations & overrides ***
+        public static string GetPublicKeyTokenString(this AssemblyName oOwner)
+        {            
+            var aPkToken = oOwner.GetPublicKeyToken();
+            if (aPkToken == null)
+                return string.Empty;
+            var oSb = new StringBuilder();
+            foreach (var nPk in aPkToken)
+                oSb.AppendFormat("{0:x2}", nPk);
+            return oSb.ToString();
+        }
+		#endregion
+		#region *** Private operations & overrides ***
+		#endregion        
+    }
+}

+ 37 - 0
Workbench/Processor/Dependencies/Reflection/Extensions/TypeExt.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Quadarax.Foundation.Core.Reflection.Extensions
+{
+    public static class TypeExt
+    {
+        public static IEnumerable<MethodInfo> GetMethodsWithAttribute<TAttribute>(this Type type, bool bInherit)where TAttribute : System.Attribute
+        {
+            var methods = type.GetMethods();
+            return methods.Where(x => x.IsDefined(typeof(TAttribute), bInherit)).ToArray();
+        }
+
+
+        public static IList<PropertyInfo> GetAllProperties(this Type type)
+        {
+            if (type == null)
+                return new List<PropertyInfo>();
+
+            var propList = new List<PropertyInfo>(type.GetProperties(BindingFlags.Instance | BindingFlags.Public)); //type.GetTypeInfo().DeclaredProperties;
+            if (type.GetTypeInfo().BaseType != null)
+            {
+                var nestedProps = GetAllProperties(type.GetTypeInfo().BaseType);
+                foreach (var prop in nestedProps)
+                {
+                    if (propList.Any(x=>x.Name == prop.Name)) continue;
+                    propList.Add(prop);
+                }
+            }
+            return propList;
+        }
+
+    }
+}

+ 119 - 0
Workbench/Processor/Dependencies/Reflection/QualifiedName.cs

@@ -0,0 +1,119 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using Quadarax.Foundation.Core.Reflection.Extensions;
+
+namespace Quadarax.Foundation.Core.Reflection
+{
+    public class QualifiedName
+    {
+        #region *** Constants ***
+        private const char CC_SEPARATOR = ',';
+        #endregion
+
+        #region *** Public Properties ***
+        // ReSharper disable MemberCanBePrivate.Global
+        // ReSharper disable UnusedAutoPropertyAccessor.Global
+        public string Name { get; private set; }
+        public string Assembly { get; private set; }
+        public string Culture { get; private set; }
+        public string Token { get; private set; }
+        public string Version { get; private set; }
+        public string AssemblyFullName { get; private set; }
+        // ReSharper restore UnusedAutoPropertyAccessor.Global
+        // ReSharper restore MemberCanBePrivate.Global
+        #endregion
+        #region *** Constructors ***
+        public QualifiedName(string sReflectionQualifiedName)
+        {
+            var aParts = sReflectionQualifiedName.Split(CC_SEPARATOR)
+                            .Select(x => x.Trim())
+                            .ToList();
+
+            if (aParts.Count==0)
+                return;
+            if (aParts.Count==1)
+            {
+                //jedna se o bud o codebase nebo assembly
+                bool bCodebase = false;
+                try
+                {
+                    var oType = Type.GetType(aParts[0].Trim(), true);
+                    SetupProperties(oType.Assembly.GetName());
+                    bCodebase = true;
+                }
+                catch{}
+                if (bCodebase)
+                {
+                    //codebase
+                    Name = aParts[0].Trim();
+                }
+                else
+                {
+                    //assembly
+                    try
+                    {                        
+                        SetupProperties(new AssemblyName(aParts[0].Trim()));
+                    }
+                    catch (System.Exception e)
+                    {
+                        ThrowCannotParse(sReflectionQualifiedName, e);
+                    }
+                }
+
+            }
+            if (aParts.Count > 1)
+            {
+                //jedna se bud o codebase, assembly nebo assembly
+                try
+                {
+                    if (aParts[1].IndexOf('=') > 0)
+                    {
+                        //assembly
+                        SetupProperties(new AssemblyName(string.Join(CC_SEPARATOR.ToString() , aParts)));
+                    }
+                    else
+                    {
+                        //codebase, assembly
+                        SetupProperties(new AssemblyName(string.Join(CC_SEPARATOR.ToString(), aParts.Skip(1))));
+                        Name = aParts[0].Trim();
+                    }
+                }
+                catch (System.Exception e)
+                {
+                    ThrowCannotParse(sReflectionQualifiedName, e);
+                }                
+            }
+            
+
+            
+        }
+        #endregion
+        #region *** Public Operations ***
+        public string GetQualifiedNameWithoutVersion()
+        {
+            return Name + CC_SEPARATOR + " " + Assembly;
+        }
+
+        public bool LiteEquals(QualifiedName oCompareObject)
+        {
+            return oCompareObject.Assembly == Assembly && oCompareObject.Name == Name;
+        }
+        #endregion
+        #region *** Private Operations ***
+        private void SetupProperties(AssemblyName oName)
+        {
+            Assembly = oName.Name;
+            AssemblyFullName = oName.FullName;
+            Culture = oName.CultureName;
+            Token = oName.GetPublicKeyTokenString();
+            Version = oName.Version!=null ? oName.Version.ToString() : string.Empty;            
+        
+        }
+        private void ThrowCannotParse(string sReflectionQualifiedName, System.Exception oInnerException)
+        {
+            throw new ArgumentException(string.Format("Cannot parse QualifiedName '{0}'!", sReflectionQualifiedName), oInnerException);
+        }
+        #endregion
+    }
+}

+ 51 - 0
Workbench/Processor/Dependencies/Reflection/TypeUtils.cs

@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Quadarax.Foundation.Core.Reflection
+{
+    public static class TypeUtils
+    {
+
+        #region *** Private Fields ***
+        private static readonly IDictionary<string, Type> m_oRemTypeCache = new Dictionary<string, Type>();
+        // ReSharper disable InconsistentNaming
+        private static readonly object @lock;
+        // ReSharper restore InconsistentNaming
+        #endregion
+        #region *** Public Properties ***
+        #endregion
+        #region *** Constructors ***
+        static TypeUtils()
+        {
+            @lock = new object();
+        }
+        #endregion
+        #region *** Public operations & overrides ***
+        public static Type GetRemoteType(string sReflectionQualifiedName)
+        {
+            if (m_oRemTypeCache.ContainsKey(sReflectionQualifiedName))
+                return m_oRemTypeCache[sReflectionQualifiedName];
+
+            var oName = new QualifiedName(sReflectionQualifiedName);
+            Type oType;
+            if (oName.Assembly == null)
+            {
+                oType = Type.GetType(oName.Name, true);
+            }
+            else
+            {
+                var oAssembly = Assembly.Load(oName.Assembly);
+                oType = oAssembly.GetType(oName.Name, true);
+            }
+            lock (@lock)
+            {
+                m_oRemTypeCache.Add(sReflectionQualifiedName, oType);
+            }
+            return oType;
+        }
+        #endregion
+        #region *** Private operations & overrides ***
+        #endregion               
+    }
+}

+ 9 - 0
Workbench/Processor/Enums/ProcessQueueTypeEnum.cs

@@ -0,0 +1,9 @@
+namespace Quadarax.Foundation.Core.Business.Processor.Enums;
+
+public enum ProcessQueueTypeEnum
+{
+   QueuePending,
+   QueueProcessing,
+   QueueSucc,
+   QueueFail
+}

+ 16 - 0
Workbench/Processor/Enums/ProcessStatusEnum.cs

@@ -0,0 +1,16 @@
+namespace Quadarax.Foundation.Core.Business.Processor.Enums;
+
+public enum ProcessStatusEnum : byte
+{
+       Initial = 0,
+       Pending = 1,
+       Attached = 2,
+       Failed = 3,
+       Started = 4,
+       Paused = 5,
+       ProcessedSucc = 10,
+       ProcessedFail = 11,
+       Deleted = 100,   
+       ExpiredValidity = 20,
+       ExpiredAttemts = 21,
+}

+ 15 - 0
Workbench/Processor/Processor.csproj

@@ -0,0 +1,15 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net6.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+    <RootNamespace>Quadarax.Foundation.Core.Business.Processor</RootNamespace>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Folder Include="Dependencies\" />
+  </ItemGroup>
+
+</Project>

+ 25 - 0
Workbench/Processor/Processor.sln

@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.7.34009.444
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Processor", "Processor.csproj", "{32B79930-C08A-44B4-8B91-E65737FAA648}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{32B79930-C08A-44B4-8B91-E65737FAA648}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{32B79930-C08A-44B4-8B91-E65737FAA648}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{32B79930-C08A-44B4-8B91-E65737FAA648}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{32B79930-C08A-44B4-8B91-E65737FAA648}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {899061BE-0BAE-4FDF-9003-F14737FCFF42}
+	EndGlobalSection
+EndGlobal

+ 2 - 0
Workbench/Processor/Program.cs

@@ -0,0 +1,2 @@
+// See https://aka.ms/new-console-template for more information
+Console.WriteLine("Hello, World!");

+ 71 - 0
Workbench/Processor/Task/AffinityToken.cs

@@ -0,0 +1,71 @@
+using System.Text;
+
+namespace Quadarax.Foundation.Core.Business.Processor.Task;
+
+public class AffinityToken : IAffinityToken
+{         
+	#region *** Constants ***
+    // ReSharper disable once InconsistentNaming
+    public const char CCH_AT_SEP = '#';
+	#endregion
+	#region *** Public properties ***
+	public string QueueIdentifier {get; private set;}
+	public int? WorkerOrdinal {get; private set;}
+	#endregion
+	
+	#region *** Constructor ***
+	public AffinityToken()
+	{
+	}
+	public AffinityToken(string queueIdentifier, int workerOrdinal)
+	{
+		Set(QueueIdentifier, workerOrdinal);
+	}
+	public AffinityToken(string affinityTokenComplex)
+	{
+		FromComplex(affinityTokenComplex);	
+	}
+    public AffinityToken(AffinityToken affinityToken)
+    {
+        if (affinityToken == null) throw new ArgumentNullException(nameof(affinityToken));
+
+        QueueIdentifier = affinityToken.QueueIdentifier;
+        WorkerOrdinal = affinityToken.WorkerOrdinal;
+    }
+	#endregion
+	
+	#region *** Public Operations ***
+	public void FromComplex(string affinityTokenComplex)
+	{
+		if (string.IsNullOrEmpty(affinityTokenComplex)) throw new ArgumentNullException(nameof(affinityTokenComplex));;
+		var parts = affinityTokenComplex.Split(CCH_AT_SEP, StringSplitOptions.RemoveEmptyEntries);
+		if (parts.Length!=2) throw new ArgumentOutOfRangeException(nameof(affinityTokenComplex),$"Invalid format of affinity complex token value '{affinityTokenComplex}'.");
+		
+		QueueIdentifier = parts[0];
+		WorkerOrdinal = int.Parse(parts[1]);
+		
+	}
+	public void Set(string queueIdentifier, int workerOrdinal)
+	{
+		if (string.IsNullOrEmpty(queueIdentifier)) throw new ArgumentNullException(nameof(queueIdentifier));
+		QueueIdentifier = queueIdentifier;
+		WorkerOrdinal = workerOrdinal;
+	}
+	
+	public override string ToString()
+	{
+		var sb = new StringBuilder();
+		if (!(string.IsNullOrEmpty(QueueIdentifier) || WorkerOrdinal == null))
+		{
+			sb.Append(QueueIdentifier).Append(CCH_AT_SEP).Append(WorkerOrdinal.Value);
+		}
+		return sb.ToString();
+	}
+	
+	public bool Equals (AffinityToken other)
+	{
+		if (other == null) return false;
+		return string.Equals(ToString(), other.ToString());
+	}
+	#endregion
+}

+ 25 - 0
Workbench/Processor/Task/IAffinityToken.cs

@@ -0,0 +1,25 @@
+namespace Quadarax.Foundation.Core.Business.Processor.Task;
+
+public interface IAffinityToken : IEquatable<AffinityToken>
+{
+    /// <summary>
+    /// Contains the queue identifier which is used to identify owning/locking queue.
+    /// </summary>
+    string QueueIdentifier { get; }
+    /// <summary>
+    /// Contains the worker ordinal which is used to identify owning/locking worker.
+    /// </summary>
+    int? WorkerOrdinal { get; }
+    /// <summary>
+    /// Setup affinity token from complex string representation.
+    /// </summary>
+    /// <param name="affinityTokenComplex">Complex affinity token representation</param>
+    void FromComplex(string affinityTokenComplex);
+    /// <summary>
+    /// Setup affinity token from queue identifier and worker ordinal.
+    /// </summary>
+    /// <param name="queueIdentifier">queue identifier</param>
+    /// <param name="workerOrdinal">Worker ordinal number</param>
+    void Set(string queueIdentifier, int workerOrdinal);
+    string ToString();
+}

+ 15 - 0
Workbench/Processor/Task/ITaskIdentifier.cs

@@ -0,0 +1,15 @@
+using Quadarax.Foundation.Core.Business.Processor.Enums;
+
+namespace Quadarax.Foundation.Core.Business.Processor.Task;
+
+public interface ITaskIdentifier 
+{         
+	/// <summary>
+	/// Primary key of the task.
+	/// </summary>
+	long Id {get;}
+	/// <summary>
+	/// Queue type of the task where task is stored or belongs to.
+	/// </summary>
+	ProcessQueueTypeEnum QueueType {get;}
+}

+ 68 - 0
Workbench/Processor/Task/ITaskItem.cs

@@ -0,0 +1,68 @@
+using Quadarax.Foundation.Core.Business.Processor.Enums;
+
+namespace Quadarax.Foundation.Core.Business.Processor.Task;
+
+public interface ITaskItem : ITaskIdentifier, ITimeTracked
+{
+	#region *** Properties ***
+	/// <summary>
+	/// Contains the affinity token which is used to identify owning/locking queue.
+	/// </summary>
+	IAffinityToken AffinityToken { get; }
+	/// <summary>
+	/// External reference of the task.
+	/// </summary>
+	public string Reference { get; }
+	/// <summary>
+	/// Status of the task.
+	/// </summary>
+    public ProcessStatusEnum Status { get; }
+	/// <summary>
+	/// Assembly qualified name of the provider class responsible to process task.
+	/// </summary>
+	public string ProviderClass { get; }
+	/// <summary>
+	/// Task priority value (0-maximal, 255-minimal / default 100).
+	/// </summary>
+	public byte Priority { get; }
+	/// <summary>
+	/// Time when task can be processed.
+	/// </summary>
+	public DateTime ProcessingValidFrom { get; }
+    /// <summary>
+    /// Time when task will be expired.
+    /// </summary>
+    public DateTime? ProcessingValidTo { get; }
+	/// <summary>
+	/// Decremental counter of attempts to try process task.
+	/// </summary>
+	public int AttemptsLeft { get; }
+	/// <summary>
+	/// Statistical timestamp when task begins to process.
+	/// </summary>
+	public DateTime StatStarted { get; }
+	/// <summary>
+	/// Statistical timestamp when task finished.
+	/// </summary>
+    public DateTime StatFinished { get; }
+	/// <summary>
+	/// Latest attempt duration
+	/// </summary>
+    public TimeSpan StatLastAttemptDuration { get; }
+    #endregion
+
+	#region *** Operations ***
+	/// <summary>
+	/// Schedules task to future and sets <see cref="Status"/> to <see cref="ProcessStatusEnum.Pending"/> (affects <see cref="ProcessingValidFrom"/> and <see cref="ProcessingValidTo"/>).
+	/// <list type="bullet">
+	///	<item><description>Allowed state: <see cref="ProcessStatusEnum.Pending"/>, <see cref="ProcessStatusEnum.Paused"/></description></item>
+    ///	<item><description>Set state to: <see cref="ProcessStatusEnum.Pending"/></description></item>
+    /// </list>
+	/// </summary>
+	/// <param name="postponeInterval">Interval to shift to future.</param>
+	/// <param name="reason">Reason message to postpone.</param>
+    void Postpone(TimeSpan postponeInterval, string reason);
+	void Stop(string reason);
+	void Reset(string reason);
+	#endregion
+}

+ 15 - 0
Workbench/Processor/Task/ITimeTracked.cs

@@ -0,0 +1,15 @@
+namespace Quadarax.Foundation.Core.Business.Processor.Task
+{
+    public interface ITimeTracked
+    {
+        /// <summary>
+        /// Timestamp when entity was created.
+        /// </summary>
+        public DateTime Created { get; }
+
+        /// <summary>
+        /// Timestamp when entity was changed.
+        /// </summary>
+        public DateTime? Changed { get; }
+    }
+}