Bläddra i källkod

enable Nullable compile requirement in all qdr.fnd projects

update Console.StartupConfiguration to add DefaultLoggerFactory
update Console.AbstractCommand to use DefaultLoggerFactory (include internal logging)
update Console reference to new qdr.fnd.core
fix QA in qdr.fnd.core (not all)
Dalibor Votruba 2 år sedan
förälder
incheckning
0344ca910a

+ 1 - 0
qdr.fnd.core.business/qdr.fnd.core.business.csproj

@@ -18,6 +18,7 @@
     <AssemblyVersion>0.0.1.0</AssemblyVersion>
     <FileVersion>0.0.1.0</FileVersion>
     <Version>0.0.1.0-alpha</Version>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <ItemGroup>

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

@@ -1,36 +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();
-        }
-    }
-}
+using Quadarax.Foundation.Core.Exceptions;
+using System;
+
+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();
+        }
+    }
+}

+ 5 - 0
qdr.fnd.core.data.itfc/qdr.fnd.core.data.itfc.csproj

@@ -18,6 +18,7 @@
     <AssemblyVersion>0.0.1.0</AssemblyVersion>
     <FileVersion>0.0.1.0</FileVersion>
     <Version>0.0.1.0-alpha</Version>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <ItemGroup>
@@ -31,4 +32,8 @@
     <PackageReference Include="qdr.fnd.core" Version="0.0.1-alpha" />
   </ItemGroup>
 
+  <ItemGroup>
+    <ProjectReference Include="..\qdr.fnd.core\qdr.fnd.core.csproj" />
+  </ItemGroup>
+
 </Project>

+ 1 - 0
qdr.fnd.core.data/qdr.fnd.core.data.csproj

@@ -18,6 +18,7 @@
     <AssemblyVersion>0.0.1.0</AssemblyVersion>
     <FileVersion>0.0.1.0</FileVersion>
     <Version>0.0.1.0-alpha</Version>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <ItemGroup>

+ 1 - 0
qdr.fnd.core.nlog/qdr.fnd.core.nlog.csproj

@@ -18,6 +18,7 @@
     <AssemblyVersion>0.0.1.0</AssemblyVersion>
     <FileVersion>0.0.1.0</FileVersion>
     <Version>0.0.1.0-alpha</Version>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <ItemGroup>

+ 22 - 8
qdr.fnd.core.qconsole/Command/Base/AbstractCommand.cs

@@ -1,8 +1,8 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
 using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.Logging;
 using Quadarax.Foundation.Core.QConsole.Argument;
 using Quadarax.Foundation.Core.QConsole.Context;
 using Quadarax.Foundation.Core.QConsole.Extensions;
@@ -24,9 +24,10 @@ namespace Quadarax.Foundation.Core.QConsole.Command.Base
         #endregion
 
         #region *** Private Fields ***
-        private Engine _engine;
-        private IDictionary<string, AbstractArgument> _arguments;
+        private readonly Engine _engine;
+        private readonly IDictionary<string, AbstractArgument> _arguments;
         protected ICommandContext _context;
+        private readonly ILog? _log;
         #endregion
 
         #region *** Properties ***
@@ -42,9 +43,10 @@ namespace Quadarax.Foundation.Core.QConsole.Command.Base
 
         #region  *** Constructor ***
 
-        public AbstractCommand(Engine engine)
+        protected AbstractCommand(Engine engine)
         {
             _engine = engine ?? throw new ArgumentNullException(nameof(engine));
+            _log = engine.Configuration.DefaultLoggerFactory?.GetLogger(GetType());
             _arguments = new Dictionary<string, AbstractArgument>();
             _context = _engine.Context.CreateCommandContext();
             WriteDebugInfo($"Context for command '{Name}' created: {_context}");
@@ -92,6 +94,7 @@ namespace Quadarax.Foundation.Core.QConsole.Command.Base
         {
             return "Command: " + Name;
         }
+
         #endregion
 
         #region *** Private operations ***
@@ -110,7 +113,7 @@ namespace Quadarax.Foundation.Core.QConsole.Command.Base
             });
 
 
-            for (int i = 1; i < args.Length; i++)
+            for (var i = 1; i < args.Length; i++)
             {
                 var arg = args[i];
                 var index = i - 1;
@@ -257,7 +260,7 @@ namespace Quadarax.Foundation.Core.QConsole.Command.Base
                 DumpException(e, string.Empty);
         }
 
-        private void DumpException(Exception e, string prefix)
+        private void DumpException(Exception? e, string prefix)
         {
             while (e != null)
             {                                         
@@ -296,7 +299,7 @@ namespace Quadarax.Foundation.Core.QConsole.Command.Base
         }
         protected virtual IEnumerable<AbstractArgument> OnSetupArguments()
         {
-            return new AbstractArgument[0];
+            return Array.Empty<AbstractArgument>();
             //{
             //    new FlagArgument(Constants.Arguments.General.DebugMode.Code, Constants.Arguments.General.DebugMode.Description, Constants.Arguments.General.DebugMode.Hint, true), 
             //};
@@ -330,6 +333,17 @@ namespace Quadarax.Foundation.Core.QConsole.Command.Base
         {
             return incommingResult;
         }
+
+        protected virtual void Log(LogSeverityEnum type, int code, string message, Exception e = null)
+        {
+            _log?.Log(type, code, message,e);
+        }
+        protected void Log(LogSeverityEnum type, string message, Exception e = null)
+        {
+            Log(type,0, message,e);
+        }
+
+
         #endregion
 
         #region *** Protected operations ***
@@ -339,7 +353,7 @@ namespace Quadarax.Foundation.Core.QConsole.Command.Base
                 throw new Exception($"Argument '{code}' is not defined.");
             return _arguments[code];
         }
-        protected AbstractArgument GetArgument(int ordinalPosition)
+        protected AbstractArgument? GetArgument(int ordinalPosition)
         {
             return _arguments.Values.Where(x => x.IsPositional()).Skip(ordinalPosition).FirstOrDefault();
         }

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

@@ -4,6 +4,7 @@ using System.Linq;
 using System.Reflection;
 using System.Xml.XPath;
 using Quadarax.Foundation.Core.Console;
+using Quadarax.Foundation.Core.Logging;
 using Quadarax.Foundation.Core.QConsole.Handlers;
 
 namespace Quadarax.Foundation.Core.QConsole.Configuration
@@ -119,6 +120,8 @@ namespace Quadarax.Foundation.Core.QConsole.Configuration
                 DebugConsoleWriter.IsWriteDebugEnabled = value;
             }
         }
+
+        public ILogger? DefaultLoggerFactory { get; set; }
         #endregion
 
         #region *** Constructor ***

+ 29 - 28
qdr.fnd.core.qconsole/qdr.fnd.core.qconsole.csproj

@@ -1,34 +1,35 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net7.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>
-    <Title>Quadarax.Foundation.Core.QConsole</Title>
-    <Authors>Dalibor Votruba</Authors>
-    <Company>Quadarax</Company>
-    <Product>Quadarax.Foundation</Product>
-    <Description>Quadarax.Foundation.Core.QConsole - abstract console engine under foundation library</Description>
-    <Copyright>Copyright © 2023 Quadarax</Copyright>
-    <PackageIcon>quadarax_dll.png</PackageIcon>
-    <PackageTags>QDR;FND;CORE;CONSOLE</PackageTags>
-    <AssemblyVersion>0.0.1.0</AssemblyVersion>
-    <FileVersion>0.0.1.0</FileVersion>
-    <Version>0.0.1.0-alpha</Version>
-  </PropertyGroup>
-
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net7.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>
+    <Title>Quadarax.Foundation.Core.QConsole</Title>
+    <Authors>Dalibor Votruba</Authors>
+    <Company>Quadarax</Company>
+    <Product>Quadarax.Foundation</Product>
+    <Description>Quadarax.Foundation.Core.QConsole - abstract console engine under foundation library</Description>
+    <Copyright>Copyright © 2023 Quadarax</Copyright>
+    <PackageIcon>quadarax_dll.png</PackageIcon>
+    <PackageTags>QDR;FND;CORE;CONSOLE</PackageTags>
+    <AssemblyVersion>0.0.2.0</AssemblyVersion>
+    <FileVersion>0.0.2.0</FileVersion>
+    <Version>0.0.2.0-alpha</Version>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
   <ItemGroup>
     <None Include="..\quadarax_dll.png">
       <Pack>True</Pack>
       <PackagePath>\</PackagePath>
     </None>
-  </ItemGroup>
-
+  </ItemGroup>
+
   <ItemGroup>
-    <PackageReference Include="qdr.fnd.core" Version="0.0.1-alpha" />
-  </ItemGroup>
-
-</Project>
+    <PackageReference Include="qdr.fnd.core" Version="0.0.2-alpha" />
+  </ItemGroup>
+
+</Project>

+ 15 - 0
qdr.fnd.core.qconsole/releasenotes.md

@@ -0,0 +1,15 @@
+# Quadarax.Foundation.Core.QConsole * Release notes
+Ordered by version descending
+
+## 0.0.2.0
+Date:__10.2.2023__
+- update dependency to qdr.fnd.core v.0.0.2.0
+- add DefaultLoggerFactory to StartupConfiguration, add Log virtual method to AbstractCommand - use logger from DefaultLoggerFactory
+- fix quality CA
+- minor fixes
+---
+## 0.0.1.0
+Date:__1.9.2023__
+- initial version
+---
+---

+ 1 - 0
qdr.fnd.core.web/qdr.fnd.core.web.csproj

@@ -18,6 +18,7 @@
     <AssemblyVersion>0.0.1.0</AssemblyVersion>
     <FileVersion>0.0.1.0</FileVersion>
     <Version>0.0.1.0-alpha</Version>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <ItemGroup>

+ 1 - 1
qdr.fnd.core/Console/ConsoleWriter.cs

@@ -36,7 +36,7 @@ namespace Quadarax.Foundation.Core.Console
             return this;
         }
 
-        public string ReadLine()
+        public string? ReadLine()
         {
             SetColor();
             return System.Console.ReadLine();

+ 3 - 3
qdr.fnd.core/Console/ProgressBar.cs

@@ -19,7 +19,7 @@ namespace Quadarax.Foundation.Core.Console
         private double _currentProgress;
         private string _currentText = string.Empty;
         private int _animationIndex;
-        private ConsoleWriter _writer;
+        private ConsoleWriter? _writer;
         #endregion
 
         #region *** Constructors ***
@@ -52,7 +52,7 @@ namespace Quadarax.Foundation.Core.Console
         #endregion
 
         #region *** Private Operations ***
-        private void TimerHandler(object state)
+        private void TimerHandler(object? state)
         {
             lock (_timer)
             {
@@ -89,7 +89,7 @@ namespace Quadarax.Foundation.Core.Console
                 outputBuilder.Append('\b', overlapCount);
             }
 
-            _writer.Write(outputBuilder.ToString());
+            _writer?.Write(outputBuilder.ToString());
             _currentText = text;
         }
 

+ 2 - 2
qdr.fnd.core/Console/ProgressConsoleWriter.cs

@@ -6,9 +6,9 @@ namespace Quadarax.Foundation.Core.Console
     public class ProgressConsoleWriter : ConsoleWriter
     {
         #region *** Private Fields ***
-        private int _maxProgress;
+        private readonly int _maxProgress;
         private int _curProgress = 0;
-        private string _lastText;
+        private string _lastText = string.Empty;
         #endregion
 
         #region *** Constructors ***

+ 7 - 3
qdr.fnd.core/Data/CsvHelper.cs

@@ -20,15 +20,19 @@ namespace Quadarax.Foundation.Core.Data
             var dt = new DataTable();
             using (var sr = new StreamReader(csvFile))
             {
-                var headers = sr.ReadLine().Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
+
+                var headers = sr?.ReadLine()?.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
+                if (headers == null) return dt;
                 foreach (var header in headers)
                 {
                     dt.Columns.Add(header);
                 }
 
-                while (!sr.EndOfStream)
+                while (sr is { EndOfStream: false })
                 {
-                    var rows = sr.ReadLine().Split(new[] { delimiter }, StringSplitOptions.None);
+                    var rows = sr?.ReadLine()?.Split(new[] { delimiter }, StringSplitOptions.None);
+                    if (rows == null) continue;
+
                     var dr = dt.NewRow();
                     for (var i = 0; i < headers.Length; i++)
                     {

+ 1 - 1
qdr.fnd.core/Data/Diff/DiffComparator.cs

@@ -59,7 +59,7 @@ namespace Quadarax.Foundation.Core.Data.Diff
             return source;
         }
 
-        private TEntry Find(object key, IEnumerable<TEntry> target)
+        private TEntry? Find(object key, IEnumerable<TEntry> target)
         {
             if (target == null)
                 throw new ArgumentNullException(nameof(target));

+ 5 - 6
qdr.fnd.core/Data/Diff/DiffEntry.cs

@@ -1,5 +1,4 @@
-using System.Threading;
-
+
 namespace Quadarax.Foundation.Core.Data.Diff
 {
     public abstract class DiffEntry
@@ -16,7 +15,7 @@ namespace Quadarax.Foundation.Core.Data.Diff
             DifferentKey
         }
 
-        public object Item { get; private set; }
+        public object? Item { get; private set; }
         public CompareStateEnum CompareState { get; private set; }
 
         protected DiffEntry(object item)
@@ -41,7 +40,7 @@ namespace Quadarax.Foundation.Core.Data.Diff
         /// </summary>
         /// <param name="other"></param>
         /// <returns>-1 = both null, 0 - current null, 1 - other null, 2 - current smaller, 3 - current bigger, 4 - equals, 5 - different key</returns>
-        public CompareStateEnum Compare(DiffEntry other)
+        public CompareStateEnum Compare(DiffEntry? other)
         {
             if (other == null && Item == null)
                 return SetCompareState(CompareStateEnum.BothNull);
@@ -56,9 +55,9 @@ namespace Quadarax.Foundation.Core.Data.Diff
             return OnCompareEquality(other);
         }
 
-        public TItem GetItem<TItem>()
+        public TItem? GetItem<TItem>()
         {
-            return (TItem)Item;
+            return (TItem?)Item;
         }
 
         /// <summary>

+ 2 - 2
qdr.fnd.core/Exceptions/ApiException.cs

@@ -4,11 +4,11 @@
     {
         public int StatusCode { get; }
 
-        public string Response { get; }
+        public string? Response { get; }
 
         public System.Collections.Generic.IReadOnlyDictionary<string, System.Collections.Generic.IEnumerable<string>> Headers { get; private set; }
 
-        public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary<string, System.Collections.Generic.IEnumerable<string>> headers, System.Exception innerException)
+        public ApiException(string message, int statusCode, string? response, System.Collections.Generic.IReadOnlyDictionary<string, System.Collections.Generic.IEnumerable<string>> headers, System.Exception innerException)
             : base(message + "\n\nStatus: " + statusCode + "\nResponse: \n" + ((response == null) ? "(null)" : response.Substring(0, response.Length >= 512 ? 512 : response.Length)), innerException)
         {
             StatusCode = statusCode;

+ 1 - 1
qdr.fnd.core/IO/Extensions/DirectoryInfoExt.cs

@@ -69,7 +69,7 @@ namespace Quadarax.Foundation.Core.IO.Extensions
             return dirInfo.Exists && dirInfo.GetDirectories(subDirectoryName, SearchOption.TopDirectoryOnly).Any();
         }
 
-        public static IDirectoryInfo GetDirectory(this IDirectoryInfo dirInfo, string subDirectoryName)
+        public static IDirectoryInfo? GetDirectory(this IDirectoryInfo dirInfo, string subDirectoryName)
         {
             if (dirInfo == null)
                 throw new ArgumentNullException(nameof(dirInfo));

+ 2 - 2
qdr.fnd.core/IO/FileSearch.cs

@@ -43,12 +43,12 @@ namespace Quadarax.Foundation.Core.IO
         {
             return Search(new[] {"*"});
         }
-        public string[] Search(IEnumerable<string> includePatterns, FileSearchComparer comparer = null)
+        public string[] Search(IEnumerable<string> includePatterns, FileSearchComparer? comparer = null)
         {
             return Search(includePatterns, new List<string>(), comparer);
         }
 
-        public string[] Search(IEnumerable<string> includePatterns, IEnumerable<string> excludePatterns, FileSearchComparer comparer = null)
+        public string[] Search(IEnumerable<string> includePatterns, IEnumerable<string> excludePatterns, FileSearchComparer? comparer = null)
         {
             if (includePatterns == null)
                 throw new ArgumentNullException(nameof(includePatterns));

+ 15 - 7
qdr.fnd.core/IO/FileUtils.cs

@@ -13,7 +13,7 @@ namespace Quadarax.Foundation.Core.IO
         private const string CS_CFG_VAR = "LocalAppData";
 
 
-        private static Regex _removeInvalidChars;
+        private static Regex? _removeInvalidChars;
 
         public static string SanitizedFileName(IFileSystem fileSystemAbstraction, string fileName, string replacement = "_")
         {
@@ -52,13 +52,16 @@ namespace Quadarax.Foundation.Core.IO
             if (fileSystemAbstraction == null && !string.IsNullOrEmpty(directoryPath))
                 throw new ArgumentNullException(nameof(fileSystemAbstraction));
 
+            var sepChar = '\\';
+            if (fileSystemAbstraction != null)
+                sepChar = fileSystemAbstraction.Path.DirectorySeparatorChar;
 
             if (string.IsNullOrEmpty(directoryPath))
                 return directoryPath;
             directoryPath = directoryPath.Trim();
-            if (directoryPath.EndsWith(fileSystemAbstraction.Path.DirectorySeparatorChar))
+            if (directoryPath.EndsWith(sepChar))
                 return directoryPath;
-            return directoryPath + fileSystemAbstraction.Path.DirectorySeparatorChar;
+            return directoryPath + sepChar;
         }
         public static string EnsurePathNotEndsWithDirSeparator(IFileSystem fileSystemAbstraction, string directoryPath)
         {
@@ -68,13 +71,13 @@ namespace Quadarax.Foundation.Core.IO
             if (string.IsNullOrEmpty(directoryPath))
                 return directoryPath;
             directoryPath = directoryPath.Trim();
-            if (!directoryPath.EndsWith(fileSystemAbstraction.Path.DirectorySeparatorChar))
+            if (fileSystemAbstraction != null && !directoryPath.EndsWith(GetDirSepChar(fileSystemAbstraction)))
                 return directoryPath;
             return directoryPath.RemoveLast();
         }
 
 
-        public static string GetConfigBasePath(IFileSystem fileSystemAbstraction)
+        public static string? GetConfigBasePath(IFileSystem fileSystemAbstraction)
         {
 #if LINUX
             return $"{fileSystemAbstraction.Path.DirectorySeparatorChar}etc";
@@ -85,7 +88,7 @@ namespace Quadarax.Foundation.Core.IO
             var localAppDir = Environment.GetEnvironmentVariable(CS_CFG_VAR);
 #endif
             if (string.IsNullOrEmpty(localAppDir))
-                return Assembly.GetEntryAssembly().Location;
+                return Assembly.GetEntryAssembly()?.Location;
             return EnsurePathNotEndsWithDirSeparator(fileSystemAbstraction, localAppDir.EnsurePathNonBackslash());
 #endif
 
@@ -97,7 +100,7 @@ namespace Quadarax.Foundation.Core.IO
 
         public static string GetLogsPath(IFileSystem fileSystemAbstraction)
         {
-            return EnsurePathNotEndsWithDirSeparator(fileSystemAbstraction,(GetLogBasePath(fileSystemAbstraction) + Path.DirectorySeparatorChar + Assembly.GetEntryAssembly().GetName().Name));
+            return EnsurePathNotEndsWithDirSeparator(fileSystemAbstraction,(GetLogBasePath(fileSystemAbstraction) + Path.DirectorySeparatorChar + Assembly.GetEntryAssembly()?.GetName().Name));
         }
 
 
@@ -110,5 +113,10 @@ namespace Quadarax.Foundation.Core.IO
 #endif
         }
 
+        private static char GetDirSepChar(IFileSystem fileSystemAbstraction)
+        {
+            var sepChar = fileSystemAbstraction.Path.DirectorySeparatorChar;
+            return sepChar;
+        }
     }
 }

+ 6 - 5
qdr.fnd.core/Json/Binder.cs

@@ -38,11 +38,11 @@ namespace Quadarax.Foundation.Core.Json
             SerializerOptions = jsonOpt;
         }
 
-        public TObject Load<TObject>(string fileName)
+        public TObject? Load<TObject>(string fileName)
         {
-            return (TObject) Load(fileName, typeof(TObject));
+            return (TObject?) Load(fileName, typeof(TObject));
         }
-        public object Load(string fileName, Type targetType)
+        public object? Load(string fileName, Type targetType)
         {
             if (targetType == null)
                 throw new ArgumentNullException(nameof(targetType));
@@ -57,7 +57,7 @@ namespace Quadarax.Foundation.Core.Json
             }
         }
 
-        public object LoadFromString(string jsonString, Type targetType)
+        public object? LoadFromString(string jsonString, Type targetType)
         {
             if (targetType == null)
                 throw new ArgumentNullException(nameof(targetType));
@@ -78,6 +78,7 @@ namespace Quadarax.Foundation.Core.Json
             if (target == null)
                 throw new ArgumentNullException(nameof(target));
             var shadow = Load(fileName, targetType);
+            if (shadow == null) throw new InvalidOperationException($"Cannot load file '{fileName}' to '{targetType.FullName}'");
             
             foreach (var property in shadow.GetType().GetProperties())
             {
@@ -86,7 +87,7 @@ namespace Quadarax.Foundation.Core.Json
                     if (property.GetType().IsClass && property.PropertyType.Assembly.FullName == targetType.Assembly.FullName)
                     {
                         var mapMethod = typeof(Binder).GetMethod("LoadTo");
-                        var genericMethod = mapMethod.MakeGenericMethod(property.GetValue(shadow).GetType());
+                        var genericMethod = mapMethod?.MakeGenericMethod(property.GetValue(shadow).GetType());
                         var obj2 = genericMethod.Invoke(null, new object[] { property.GetValue(shadow), JsonSerializer.Serialize(property.GetValue(shadow)) });
 
                         foreach (var property2 in obj2.GetType().GetProperties())

+ 17 - 12
qdr.fnd.core/Thread/AbstractWorker.cs

@@ -11,10 +11,10 @@ namespace Quadarax.Foundation.Core.Thread
     {
 
         #region *** Private fields ***
-        private Task _thread;
-        private ILog _log;
+        private Task? _thread;
+        private ILog? _log;
         private TimeSpan _delay;
-        private CancellationTokenSource _cancel;
+        private CancellationTokenSource? _cancel;
         #endregion
 
         #region *** Properties ***
@@ -23,7 +23,7 @@ namespace Quadarax.Foundation.Core.Thread
         public string Name { get; }
         public int CurrentThreadId => System.Threading.Thread.CurrentThread.ManagedThreadId;
         public TimeSpan Timeout { get; set; }
-        public IWorkerContext Context { get; private set; }
+        public IWorkerContext? Context { get; private set; }
         #endregion
 
         #region *** Constructors ***
@@ -39,7 +39,7 @@ namespace Quadarax.Foundation.Core.Thread
         {
 
         }
-        protected AbstractWorker(string workerName, IWorkerContext context, ILogger logger = null)
+        protected AbstractWorker(string workerName, IWorkerContext? context, ILogger? logger = null)
         {
             if (string.IsNullOrEmpty(workerName))
                 throw new ArgumentNullException(nameof(workerName));
@@ -47,6 +47,8 @@ namespace Quadarax.Foundation.Core.Thread
             Context = context ?? new BasicWorkerContext();
             _log = logger?.GetLogger(GetType());
             Timeout = TimeSpan.Zero;
+            _thread = null;
+            _cancel = null;
         }
         #endregion
 
@@ -68,9 +70,12 @@ namespace Quadarax.Foundation.Core.Thread
             OnBeforeStart();
 
             _cancel = new CancellationTokenSource();
-            Context.Cancel = _cancel.Token;
-            _delay = runDelay;
-            _thread = Task.Factory.StartNew(() => DoInternal(this), Context.Cancel);
+            if (Context != null)
+            {
+                Context.Cancel = _cancel.Token;
+                _delay = runDelay;
+                _thread = Task.Factory.StartNew(() => DoInternal(this), Context.Cancel);
+            }
             IsRunning = true;
             
         }
@@ -98,7 +103,7 @@ namespace Quadarax.Foundation.Core.Thread
         {
         }
 #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
-        protected virtual async Task Do(IWorkerContext context)
+        protected virtual async Task Do(IWorkerContext? context)
 #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
         {
             throw new NotImplementedException("AbstractWorker.Do() must be overriden.");
@@ -128,7 +133,7 @@ namespace Quadarax.Foundation.Core.Thread
         {
             var wk = (AbstractWorker)context;
             if (wk._delay != TimeSpan.Zero)
-                wk._thread.Wait(wk._delay);
+                wk._thread?.Wait(wk._delay);
             wk.IsTransient = false;
             try
             {
@@ -152,8 +157,8 @@ namespace Quadarax.Foundation.Core.Thread
         {
             if (_thread == null)
                 return;
-            _cancel.Cancel();
-            _cancel.Dispose();
+            _cancel?.Cancel();
+            _cancel?.Dispose();
             _cancel = null;
             _thread = null;
             IsRunning = false;

+ 6 - 6
qdr.fnd.core/Thread/LoopWorker.cs

@@ -9,7 +9,7 @@ namespace Quadarax.Foundation.Core.Thread
         #region *** Private fields ***
         private TimeSpan _defaultTimeout;
         private long _cntLimit;
-        private Func<IWorkerContext, Task> _customIteration;
+        private Func<IWorkerContext?, Task>? _customIteration;
         #endregion
 
         #region *** Properties ***
@@ -22,17 +22,17 @@ namespace Quadarax.Foundation.Core.Thread
         {
 
         }
-        public LoopWorker(string workerName, IWorkerContext context) : base(workerName, context)
+        public LoopWorker(string workerName, IWorkerContext? context) : base(workerName, context)
         {
         }
         public LoopWorker(string workerName) : base(workerName)
         {
 
         }
-        public LoopWorker(string workerName, IWorkerContext context, ILogger logger = null) : base(workerName, context, logger)
+        public LoopWorker(string workerName, IWorkerContext? context, ILogger? logger = null) : base(workerName, context, logger)
         {
         }
-        public LoopWorker(string workerName, IWorkerContext context,Func<IWorkerContext, Task> customIteration = null, ILogger logger = null) : base(workerName, context, logger)
+        public LoopWorker(string workerName, IWorkerContext? context,Func<IWorkerContext?, Task>? customIteration = null, ILogger? logger = null) : base(workerName, context, logger)
         {
             _customIteration = customIteration;
         }
@@ -43,7 +43,7 @@ namespace Quadarax.Foundation.Core.Thread
 
         #region *** Virtuals and protected ***
 
-        protected override async Task Do(IWorkerContext context)
+        protected override async Task Do(IWorkerContext? context)
         {
             var exit = false;
             var first = true;
@@ -74,7 +74,7 @@ namespace Quadarax.Foundation.Core.Thread
             }
         }
 #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
-        protected virtual async Task DoIteration(IWorkerContext context)
+        protected virtual async Task DoIteration(IWorkerContext? context)
 #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
         {
         }

+ 2 - 2
qdr.fnd.core/Value/ValueConverter.cs

@@ -5,7 +5,7 @@ namespace Quadarax.Foundation.Core.Value
     public static class ValueConverter
     {
 
-        public static object ConvertTo(Type toType, string value)
+        public static object? ConvertTo(Type toType, string value)
         {
             if (string.IsNullOrEmpty(value)) return null;
 
@@ -33,7 +33,7 @@ namespace Quadarax.Foundation.Core.Value
 
         public static TValue? ConvertTo<TValue>(string value)
         {
-            return (TValue)ConvertTo(typeof(TValue), value);
+            return (TValue?)ConvertTo(typeof(TValue), value);
         }
     }
 }

+ 1 - 0
qdr.fnd.core/qdr.fnd.core.csproj

@@ -26,6 +26,7 @@
 - fix quality CA
 - minor fixes</PackageReleaseNotes>
     <PackageReadmeFile>releasenotes.md</PackageReadmeFile>
+    <Nullable>enable</Nullable>
 
   </PropertyGroup>