Serialize converters were added
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
using StructureHelperCommon.Infrastructures.Exceptions;
|
||||
using StructureHelperCommon.Models;
|
||||
using StructureHelperCommon.Models.Projects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace StructureHelperCommon.Infrastructures.Interfaces
|
||||
{
|
||||
public class DictionaryConvertStrategy<T, V> : IConvertStrategy<T, V>
|
||||
where T : ISaveable
|
||||
where V : ISaveable
|
||||
{
|
||||
public IShiftTraceLogger? TraceLogger { get; set; }
|
||||
public IConvertStrategy<T,V> ConvertStrategy { get; set; }
|
||||
public Dictionary<(Guid id, Type type), ISaveable> ReferenceDictionary { get; set; }
|
||||
public T ConvertFrom(V source)
|
||||
{
|
||||
ICheckInputData();
|
||||
T val;
|
||||
var key = (source.Id, typeof(T));
|
||||
if (ReferenceDictionary.ContainsKey(key))
|
||||
{
|
||||
ISaveable existValue;
|
||||
ReferenceDictionary.TryGetValue(key, out existValue);
|
||||
val = (T)existValue;
|
||||
TraceLogger?.AddMessage($"Value of {typeof(T)} (Id = {existValue.Id}) exists already", TraceLogStatuses.Debug);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = ConvertStrategy.ConvertFrom(source);
|
||||
ReferenceDictionary.Add(key, val);
|
||||
TraceLogger?.AddMessage($"New value of {typeof(T)} (Id = {val.Id}) was added to dictionary", TraceLogStatuses.Debug);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
public V ConvertTo(T source)
|
||||
{
|
||||
ICheckInputData();
|
||||
V val;
|
||||
var key = (source.Id, typeof(V));
|
||||
if (ReferenceDictionary.ContainsKey(key))
|
||||
{
|
||||
ISaveable existValue;
|
||||
ReferenceDictionary.TryGetValue(key, out existValue);
|
||||
val = (V)existValue;
|
||||
TraceLogger?.AddMessage($"Value of {typeof(V)} (Id = {existValue.Id}) exists already", TraceLogStatuses.Debug);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = ConvertStrategy.ConvertTo(source);
|
||||
ReferenceDictionary.Add(key, val);
|
||||
TraceLogger?.AddMessage($"New value of {typeof(V)} (Id = {val.Id}) was added to dictionary", TraceLogStatuses.Debug);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
private void ICheckInputData()
|
||||
{
|
||||
if(ReferenceDictionary is null)
|
||||
{
|
||||
string errorString = ErrorStrings.ParameterIsNull + ": Reference Dictionary";
|
||||
TraceLogger?.AddMessage(errorString, TraceLogStatuses.Error);
|
||||
throw new StructureHelperException(errorString);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using StructureHelperCommon.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Infrastructures.Interfaces
|
||||
{
|
||||
public interface IConvertStrategy<T,V>
|
||||
where T :ISaveable
|
||||
where V :ISaveable
|
||||
{
|
||||
IShiftTraceLogger TraceLogger { get; set; }
|
||||
V ConvertTo(T source);
|
||||
T ConvertFrom(V source);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,9 @@ using StructureHelperCommon.Models.Codes;
|
||||
using StructureHelperCommon.Models.Codes.Factories;
|
||||
using StructureHelperCommon.Models.Materials;
|
||||
using StructureHelperCommon.Models.Materials.Libraries;
|
||||
using StructureHelperCommon.Models.Projects;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Design.Serialization;
|
||||
using System.Linq;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Navigation;
|
||||
@@ -55,7 +57,15 @@ namespace StructureHelperCommon.Infrastructures.Settings
|
||||
return materialRepository;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<IProject> Projects { get; } = new();
|
||||
public static IProject CurrentProject
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Projects.Any()) { return Projects[0]; }
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static List<IMaterialLogic> MaterialLogics
|
||||
{
|
||||
get
|
||||
@@ -64,5 +74,21 @@ namespace StructureHelperCommon.Infrastructures.Settings
|
||||
return materialLogics;
|
||||
}
|
||||
}
|
||||
public static void SetCurrentProjectToNotActual()
|
||||
{
|
||||
if (CurrentProject is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
CurrentProject.IsActual = false;
|
||||
}
|
||||
public static IFileVersion GetCurrentFileVersion()
|
||||
{
|
||||
return new FileVersion()
|
||||
{
|
||||
VersionNumber = 1,
|
||||
SubVersionNumber = 0
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
StructureHelperCommon/Models/Analyses/IVisualAnalysis.cs
Normal file
16
StructureHelperCommon/Models/Analyses/IVisualAnalysis.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using StructureHelperCommon.Infrastructures.Interfaces;
|
||||
using StructureHelperCommon.Models.Analyses;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Models.Analyses
|
||||
{
|
||||
public interface IVisualAnalysis : ISaveable
|
||||
{
|
||||
IAnalysis Analysis {get;set;}
|
||||
void Run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using StructureHelperCommon.Infrastructures.Exceptions;
|
||||
using StructureHelperCommon.Infrastructures.Interfaces;
|
||||
using StructureHelperCommon.Infrastructures.Settings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Documents;
|
||||
|
||||
namespace StructureHelperCommon.Models.Projects
|
||||
{
|
||||
public class CheckFileVersionLogic : ICheckLogic
|
||||
{
|
||||
private const string checkIsGood = "Checking is good";
|
||||
|
||||
public IFileVersion? FileVersion { get; set; }
|
||||
public string CheckResult { get; private set; } = string.Empty;
|
||||
|
||||
public IShiftTraceLogger? TraceLogger { get; set; }
|
||||
|
||||
public bool Check()
|
||||
{
|
||||
if (FileVersion is null)
|
||||
{
|
||||
throw new StructureHelperException(ErrorStrings.ParameterIsNull + ": File Version");
|
||||
}
|
||||
var currentVersion = ProgramSetting.GetCurrentFileVersion();
|
||||
if (currentVersion.VersionNumber < FileVersion.VersionNumber)
|
||||
{
|
||||
string message = $"File version {FileVersion.VersionNumber} is bigger than suitable version {currentVersion.VersionNumber}";
|
||||
TraceLogger?.AddMessage(message, TraceLogStatuses.Error);
|
||||
CheckResult += message;
|
||||
return false;
|
||||
}
|
||||
if (currentVersion.SubVersionNumber < FileVersion.SubVersionNumber)
|
||||
{
|
||||
string message = $"File version {FileVersion.VersionNumber}.{FileVersion.SubVersionNumber} is bigger than suitable version {currentVersion.VersionNumber}.{currentVersion.VersionNumber}";
|
||||
TraceLogger?.AddMessage(message, TraceLogStatuses.Error);
|
||||
CheckResult += message;
|
||||
return false;
|
||||
}
|
||||
CheckResult += checkIsGood;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
StructureHelperCommon/Models/Projects/FileVersion.cs
Normal file
23
StructureHelperCommon/Models/Projects/FileVersion.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Models.Projects
|
||||
{
|
||||
public class FileVersion : IFileVersion
|
||||
{
|
||||
public Guid Id { get; }
|
||||
public int VersionNumber { get; set; }
|
||||
public int SubVersionNumber { get; set; }
|
||||
public FileVersion(Guid id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
public FileVersion() : this(Guid.NewGuid())
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using StructureHelperCommon.Infrastructures.Interfaces;
|
||||
using StructureHelperCommon.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Models.Projects
|
||||
{
|
||||
public class FileVersionUpdateStrategy : IUpdateStrategy<IFileVersion>
|
||||
{
|
||||
public void Update(IFileVersion targetObject, IFileVersion sourceObject)
|
||||
{
|
||||
CheckObject.IsNull(targetObject, sourceObject);
|
||||
if (ReferenceEquals(targetObject, sourceObject)) { return; };
|
||||
targetObject.VersionNumber = sourceObject.VersionNumber;
|
||||
targetObject.SubVersionNumber = sourceObject.SubVersionNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
StructureHelperCommon/Models/Projects/IFileVersion.cs
Normal file
15
StructureHelperCommon/Models/Projects/IFileVersion.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using StructureHelperCommon.Infrastructures.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Models.Projects
|
||||
{
|
||||
public interface IFileVersion : ISaveable
|
||||
{
|
||||
int VersionNumber { get; set; }
|
||||
int SubVersionNumber { get; set; }
|
||||
}
|
||||
}
|
||||
19
StructureHelperCommon/Models/Projects/IProject.cs
Normal file
19
StructureHelperCommon/Models/Projects/IProject.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using StructureHelperCommon.Infrastructures.Interfaces;
|
||||
using StructureHelperCommon.Models.Analyses;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Models.Projects
|
||||
{
|
||||
public interface IProject : ISaveable
|
||||
{
|
||||
string FullFileName { get; set; }
|
||||
string FileName { get; }
|
||||
bool IsNewFile { get; set; }
|
||||
bool IsActual { get; set; }
|
||||
List<IVisualAnalysis> VisualAnalyses { get;}
|
||||
}
|
||||
}
|
||||
31
StructureHelperCommon/Models/Projects/Project.cs
Normal file
31
StructureHelperCommon/Models/Projects/Project.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using StructureHelperCommon.Infrastructures.Interfaces;
|
||||
using StructureHelperCommon.Models.Analyses;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Models.Projects
|
||||
{
|
||||
public class Project : IProject
|
||||
{
|
||||
public Guid Id { get; }
|
||||
public string FullFileName { get; set; } = string.Empty;
|
||||
public bool IsActual { get; set; } = true;
|
||||
public List<IVisualAnalysis> VisualAnalyses { get; } = new();
|
||||
public bool IsNewFile { get; set; } = true;
|
||||
public string FileName => Path.GetFileName(FullFileName);
|
||||
|
||||
public Project(Guid id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public Project() : this(Guid.NewGuid())
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DataAccess.FileDialogs
|
||||
{
|
||||
public class FileDialogOpener
|
||||
{
|
||||
public void OpenFileAndRead()
|
||||
{
|
||||
//// Create an instance of OpenFileDialog
|
||||
//using OpenFileDialog openFileDialog = new();
|
||||
//// Set filter options and filter index
|
||||
//openFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
|
||||
//openFileDialog.FilterIndex = 1;
|
||||
//openFileDialog.Multiselect = false; // Set to true if you want to allow multiple file selection
|
||||
//openFileDialog.Title = "Select a File";
|
||||
|
||||
//// Show the dialog and get result
|
||||
//if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||||
//{
|
||||
// // Get the path of the selected file
|
||||
// string selectedFilePath = openFileDialog.FileName;
|
||||
|
||||
// // Read the content of the file
|
||||
// try
|
||||
// {
|
||||
// string fileContent = File.ReadAllText(selectedFilePath);
|
||||
// Console.WriteLine($"File Content of '{selectedFilePath}':");
|
||||
// Console.WriteLine(fileContent);
|
||||
// }
|
||||
// catch (IOException ex)
|
||||
// {
|
||||
// Console.WriteLine($"An error occurred while reading the file: {ex.Message}");
|
||||
// }
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// Console.WriteLine("File selection was cancelled.");
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using StructureHelperCommon.Infrastructures.Exceptions;
|
||||
using StructureHelperCommon.Infrastructures.Interfaces;
|
||||
using StructureHelperCommon.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace StructureHelperCommon.Services.FileServices
|
||||
{
|
||||
public class FileDialogSaver : IFileDialogSaver
|
||||
{
|
||||
private const string saveCanceledByUser = "Saving was canceled by user";
|
||||
SaveFileResult result;
|
||||
public SaveDialogInputData? InputData { get; set; }
|
||||
public IShiftTraceLogger? TraceLogger { get; set; }
|
||||
|
||||
public SaveFileResult SaveFile()
|
||||
{
|
||||
CheckInput();
|
||||
result = new();
|
||||
using SaveFileDialog saveFileDialog = new();
|
||||
saveFileDialog.Filter = InputData.FilterString;
|
||||
saveFileDialog.InitialDirectory = InputData.InitialDirectory;
|
||||
saveFileDialog.FilterIndex = InputData.FilterIndex;
|
||||
saveFileDialog.CheckFileExists = InputData.CheckFileExist;
|
||||
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
TraceLogger?.AddMessage($"User selected file {saveFileDialog.FileName}", TraceLogStatuses.Debug);
|
||||
result.FileName = saveFileDialog.FileName;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceLogger?.AddMessage(saveCanceledByUser);
|
||||
result.IsValid = false;
|
||||
result.Description += saveCanceledByUser;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckInput()
|
||||
{
|
||||
if (InputData is null)
|
||||
{
|
||||
string errorString = ErrorStrings.ParameterIsNull + ": Input Data";
|
||||
TraceLogger?.AddMessage(errorString, TraceLogStatuses.Error);
|
||||
throw new StructureHelperException(errorString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
StructureHelperCommon/Services/FileServices/FileOpener.cs
Normal file
79
StructureHelperCommon/Services/FileServices/FileOpener.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using StructureHelperCommon.Models;
|
||||
using StructureHelperCommon.Infrastructures.Exceptions;
|
||||
|
||||
namespace StructureHelperCommon.Services.FileServices
|
||||
{
|
||||
public class FileOpener : IFileDialogOpener
|
||||
{
|
||||
private const string fileSelectionWasCanceled = "File selection was cancelled by user";
|
||||
OpenFileResult? result;
|
||||
IShiftTraceLogger? traceLogger;
|
||||
public OpenFileInputData? InputData { get; private set; }
|
||||
public FileOpener(OpenFileInputData inputData)
|
||||
{
|
||||
InputData = inputData;
|
||||
}
|
||||
public OpenFileResult OpenFile()
|
||||
{
|
||||
PrepareNewResult();
|
||||
CheckInputData();
|
||||
traceLogger = InputData.TraceLogger;
|
||||
ShowOpenFileDialog();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void ShowOpenFileDialog()
|
||||
{
|
||||
using (OpenFileDialog openFileDialog = new OpenFileDialog())
|
||||
{
|
||||
// Set filter options and filter index
|
||||
openFileDialog.Filter = InputData.FilterString;
|
||||
openFileDialog.FilterIndex = InputData.FilterIndex;
|
||||
openFileDialog.Multiselect = InputData.MultiSelect;
|
||||
openFileDialog.Title = InputData.Title;
|
||||
|
||||
// Show the dialog and get result
|
||||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
// Get the path of the selected file
|
||||
string selectedFilePath = openFileDialog.FileName;
|
||||
traceLogger?.AddMessage($"File {selectedFilePath} is selected by user", TraceLogStatuses.Debug);
|
||||
result.FilePath = selectedFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.IsValid = false;
|
||||
result.Description = fileSelectionWasCanceled;
|
||||
traceLogger?.AddMessage(fileSelectionWasCanceled, TraceLogStatuses.Debug);
|
||||
Console.WriteLine(fileSelectionWasCanceled);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void CheckInputData()
|
||||
{
|
||||
if (InputData is null)
|
||||
{
|
||||
result.IsValid = false;
|
||||
string message = ErrorStrings.ParameterIsNull + ": Input Data";
|
||||
result.Description = message;
|
||||
throw new StructureHelperException(message);
|
||||
}
|
||||
}
|
||||
private void PrepareNewResult()
|
||||
{
|
||||
result = new()
|
||||
{
|
||||
IsValid = true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace StructureHelperCommon.Services.FileServices
|
||||
{
|
||||
public interface IFileDialogOpener
|
||||
{
|
||||
OpenFileInputData? InputData { get; }
|
||||
|
||||
OpenFileResult OpenFile();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using StructureHelperCommon.Infrastructures.Interfaces;
|
||||
|
||||
namespace StructureHelperCommon.Services.FileServices
|
||||
{
|
||||
public interface IFileDialogSaver : ILogic
|
||||
{
|
||||
SaveFileResult SaveFile();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using StructureHelperCommon.Models;
|
||||
using StructureHelperCommon.Models.Calculators;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Services.FileServices
|
||||
{
|
||||
public class OpenFileInputData : IInputData
|
||||
{
|
||||
public IShiftTraceLogger? TraceLogger { get; set; }
|
||||
public string FilterString { get; set; } = string.Empty;
|
||||
public int FilterIndex { get; set; } = 1;
|
||||
public bool MultiSelect { get; set; } = false;
|
||||
public string Title { get; set; } = "Select a file";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using StructureHelperCommon.Models.Calculators;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Services.FileServices
|
||||
{
|
||||
public class OpenFileResult : IResult
|
||||
{
|
||||
public bool IsValid { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string FilePath { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using StructureHelperCommon.Models.Calculators;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Services.FileServices
|
||||
{
|
||||
public class SaveDialogInputData : IInputData
|
||||
{
|
||||
public string InitialDirectory { get; set; }
|
||||
public int FilterIndex { get; set; } = 1;
|
||||
public string FilterString { get; set; } = string.Empty;
|
||||
public bool CheckFileExist { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using StructureHelperCommon.Models.Calculators;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StructureHelperCommon.Services.FileServices
|
||||
{
|
||||
public class SaveFileResult : IResult
|
||||
{
|
||||
public bool IsValid { get; set; } = true;
|
||||
public string? Description { get; set; } = string.Empty;
|
||||
public string FileName { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.2.8" />
|
||||
<PackageReference Include="NLog" Version="5.3.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user