Business Logic done...
This commit is contained in:
parent
242c0c3a4e
commit
9f505c53e6
@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PersonnelDepartmentDataMode
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PersonnelDepartmentContracts", "PersonnelDepartmentContracts\PersonnelDepartmentContracts.csproj", "{BE6B55EA-E7C1-4F66-B481-0CC9435922DD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PersonnelDepartmentBusinessLogic", "PersonnelDepartmentBusinessLogic\PersonnelDepartmentBusinessLogic.csproj", "{068D2B5D-C715-428B-A77D-A9D1E8849762}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -27,6 +29,10 @@ Global
|
||||
{BE6B55EA-E7C1-4F66-B481-0CC9435922DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BE6B55EA-E7C1-4F66-B481-0CC9435922DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BE6B55EA-E7C1-4F66-B481-0CC9435922DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{068D2B5D-C715-428B-A77D-A9D1E8849762}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{068D2B5D-C715-428B-A77D-A9D1E8849762}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{068D2B5D-C715-428B-A77D-A9D1E8849762}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{068D2B5D-C715-428B-A77D-A9D1E8849762}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -0,0 +1,90 @@
|
||||
using PersonnelDepartmentContracts.BindingModels;
|
||||
using PersonnelDepartmentContracts.BusinessLogicContracts;
|
||||
using PersonnelDepartmentContracts.StoragesContracts;
|
||||
using PersonnelDepartmentDataModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PersonnelDepartmentBusinessLogic.BusinessLogics
|
||||
{
|
||||
public class BackUpLogic : IBackUpLogic
|
||||
{
|
||||
private readonly IBackUpInfo _backUpInfo;
|
||||
|
||||
public BackUpLogic(IBackUpInfo backUpInfo)
|
||||
{
|
||||
_backUpInfo = backUpInfo;
|
||||
}
|
||||
|
||||
public void CreateBackUp(BackUpBinidngModel model)
|
||||
{
|
||||
if (_backUpInfo == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var dirInfo = new DirectoryInfo(model.FolderName);
|
||||
if (dirInfo.Exists)
|
||||
{
|
||||
foreach (var file in dirInfo.GetFiles())
|
||||
{
|
||||
file.Delete();
|
||||
}
|
||||
}
|
||||
string fileName = $"{model.FolderName}.zip";
|
||||
if (File.Exists(fileName))
|
||||
{
|
||||
File.Delete(fileName);
|
||||
}
|
||||
var typeIId = typeof(IId);
|
||||
var assembly = typeIId.Assembly;
|
||||
if (assembly == null)
|
||||
{
|
||||
throw new ArgumentNullException("Сборка не найдена", nameof(assembly));
|
||||
}
|
||||
var types = assembly.GetTypes();
|
||||
var method = GetType().GetMethod("SaveToFile", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
foreach (var type in types)
|
||||
{
|
||||
if (type.IsInterface && type.GetInterface(typeIId.Name) != null)
|
||||
{
|
||||
var modelType = _backUpInfo.GetTypeByModelInterface(type.Name);
|
||||
if (modelType == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Не найден класс-модель для {type.Name}");
|
||||
}
|
||||
// вызываем метод на выполнение
|
||||
method?.MakeGenericMethod(modelType).Invoke(this, new object[] { model.FolderName });
|
||||
}
|
||||
}
|
||||
// архивируем
|
||||
ZipFile.CreateFromDirectory(model.FolderName, fileName);
|
||||
// удаляем папку
|
||||
dirInfo.Delete(true);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveToFile<T>(string folderName) where T : class, new()
|
||||
{
|
||||
var records = _backUpInfo.GetList<T>();
|
||||
if (records == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var jsonFormatter = new DataContractJsonSerializer(typeof(List<T>));
|
||||
using var fs = new FileStream(string.Format("{0}/{1}.json", folderName, typeof(T).Name), FileMode.OpenOrCreate);
|
||||
jsonFormatter.WriteObject(fs, records);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
using PersonnelDepartmentContracts.BindingModels;
|
||||
using PersonnelDepartmentContracts.BusinessLogicContracts;
|
||||
using PersonnelDepartmentContracts.SearchModels;
|
||||
using PersonnelDepartmentContracts.StoragesContracts;
|
||||
using PersonnelDepartmentContracts.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PersonnelDepartmentBusinessLogic.BusinessLogics
|
||||
{
|
||||
public class DealLogic : IDealLogic
|
||||
{
|
||||
private readonly IDealStorage _dealStorage;
|
||||
|
||||
public DealLogic(IDealStorage dealStorage)
|
||||
{
|
||||
_dealStorage = dealStorage ?? throw new ArgumentNullException(nameof(dealStorage));
|
||||
}
|
||||
|
||||
public bool ClearList()
|
||||
{
|
||||
return _dealStorage.ClearList();
|
||||
}
|
||||
|
||||
public bool Create(DealBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_dealStorage.Insert(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Delete(DealBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_dealStorage.Delete(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public string DiffGetTest(int count)
|
||||
{
|
||||
return _dealStorage.DiffGetTest(count);
|
||||
}
|
||||
|
||||
public string GetTest(int count)
|
||||
{
|
||||
return _dealStorage.GetTest(count);
|
||||
}
|
||||
|
||||
public DealViewModel? ReadElement(DealSearchModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
var element = _dealStorage.GetElement(model);
|
||||
if (element == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
public List<DealViewModel>? ReadList(DealSearchModel? model)
|
||||
{
|
||||
var list = model == null ? _dealStorage.GetFullList() : _dealStorage.GetFilteredList(model);
|
||||
if (list == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public string SetTest(int count)
|
||||
{
|
||||
return _dealStorage.SetTest(count);
|
||||
}
|
||||
|
||||
public bool Update(DealBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_dealStorage.Update(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CheckModel(DealBindingModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
if (model.DepartmentId < 0)
|
||||
{
|
||||
throw new ArgumentNullException("Некорректный идентификатор отдела",
|
||||
nameof(model.DepartmentId));
|
||||
}
|
||||
if (model.EmployeeId < 0)
|
||||
{
|
||||
throw new ArgumentNullException("Некорректный идентификатор сотрудника",
|
||||
nameof(model.EmployeeId));
|
||||
}
|
||||
if (model.PositionId < 0)
|
||||
{
|
||||
throw new ArgumentNullException("Некорректный идентификатор должности",
|
||||
nameof(model.PositionId));
|
||||
}
|
||||
if (model.TypeId < 0)
|
||||
{
|
||||
throw new ArgumentNullException("Некорректный идентификатор типа договора",
|
||||
nameof(model.TypeId));
|
||||
}
|
||||
if (_dealStorage.GetElement(new DealSearchModel
|
||||
{
|
||||
DateFrom = model.DateFrom,
|
||||
DateTo = model.DateTo,
|
||||
DepartmentId = model.DepartmentId,
|
||||
EmployeeId = model.EmployeeId,
|
||||
PositionId = model.PositionId,
|
||||
TypeId = model.TypeId
|
||||
}) != null)
|
||||
{
|
||||
throw new InvalidOperationException("Договор с такими атрибутами уже есть");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
using PersonnelDepartmentContracts.BindingModels;
|
||||
using PersonnelDepartmentContracts.BusinessLogicContracts;
|
||||
using PersonnelDepartmentContracts.SearchModels;
|
||||
using PersonnelDepartmentContracts.StoragesContracts;
|
||||
using PersonnelDepartmentContracts.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PersonnelDepartmentBusinessLogic.BusinessLogics
|
||||
{
|
||||
public class DepartmentLogic : IDepartmentLogic
|
||||
{
|
||||
private readonly IDepartmentStorage _departmentStorage;
|
||||
|
||||
public DepartmentLogic(IDepartmentStorage departmentStorage)
|
||||
{
|
||||
_departmentStorage = departmentStorage ?? throw new ArgumentNullException(nameof(departmentStorage));
|
||||
}
|
||||
|
||||
public bool Create(DepartmentBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_departmentStorage.Insert(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Delete(DepartmentBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_departmentStorage.Delete(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public DepartmentViewModel? ReadElement(DepartmentSearchModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
var element = _departmentStorage.GetElement(model);
|
||||
if (element == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
public List<DepartmentViewModel>? ReadList(DepartmentSearchModel? model)
|
||||
{
|
||||
var list = model == null ? _departmentStorage.GetFullList() : _departmentStorage.GetFilteredList(model);
|
||||
if (list == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public bool Update(DepartmentBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_departmentStorage.Update(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CheckModel(DepartmentBindingModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
if (string.IsNullOrEmpty(model.Name))
|
||||
{
|
||||
throw new ArgumentException("Отсутвует название",
|
||||
nameof(model.Name));
|
||||
}
|
||||
if (model.Telephone < 0)
|
||||
{
|
||||
throw new ArgumentException("Некоректный контактный телефон",
|
||||
nameof(model.Telephone));
|
||||
}
|
||||
if (_departmentStorage.GetElement(new DepartmentSearchModel
|
||||
{
|
||||
Name = model.Name,
|
||||
Telephone = model.Telephone
|
||||
}) != null)
|
||||
{
|
||||
throw new InvalidOperationException("Отдел с такими атрибутами уже есть");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
using PersonnelDepartmentContracts.BindingModels;
|
||||
using PersonnelDepartmentContracts.BusinessLogicContracts;
|
||||
using PersonnelDepartmentContracts.SearchModels;
|
||||
using PersonnelDepartmentContracts.StoragesContracts;
|
||||
using PersonnelDepartmentContracts.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PersonnelDepartmentBusinessLogic.BusinessLogics
|
||||
{
|
||||
public class EmployeeLogic : IEmployeeLogic
|
||||
{
|
||||
private readonly IEmployeeStorage _employeeStorage;
|
||||
|
||||
public EmployeeLogic(IEmployeeStorage employeeStorage)
|
||||
{
|
||||
_employeeStorage = employeeStorage ?? throw new ArgumentNullException(nameof(employeeStorage));
|
||||
}
|
||||
|
||||
public bool Create(EmployeeBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_employeeStorage.Insert(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Delete(EmployeeBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_employeeStorage.Delete(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public EmployeeViewModel? ReadElement(EmployeeSearchModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
var element = _employeeStorage.GetElement(model);
|
||||
if (element == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
public List<EmployeeViewModel>? ReadList(EmployeeSearchModel? model)
|
||||
{
|
||||
var list = model == null ? _employeeStorage.GetFullList() : _employeeStorage.GetFilteredList(model);
|
||||
if (list == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public bool Update(EmployeeBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_employeeStorage.Update(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CheckModel(EmployeeBindingModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
if (string.IsNullOrEmpty(model.FirstName))
|
||||
{
|
||||
throw new ArgumentException("Отсутвует имя сотрудника",
|
||||
nameof(model.FirstName));
|
||||
}
|
||||
if (string.IsNullOrEmpty(model.LastName))
|
||||
{
|
||||
throw new ArgumentException("Отсутвует фамилия сотрудника",
|
||||
nameof(model.LastName));
|
||||
}
|
||||
if (string.IsNullOrEmpty(model.Patronymic))
|
||||
{
|
||||
throw new ArgumentException("Отсутвует отчество сотрудника",
|
||||
nameof(model.Patronymic));
|
||||
}
|
||||
if (_employeeStorage.GetElement(new EmployeeSearchModel
|
||||
{
|
||||
FirstName = model.FirstName,
|
||||
LastName = model.LastName,
|
||||
Patronymic = model.Patronymic
|
||||
}) != null)
|
||||
{
|
||||
throw new InvalidOperationException("Сотрудник с такими атрибутами уже есть");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
using PersonnelDepartmentContracts.BindingModels;
|
||||
using PersonnelDepartmentContracts.BusinessLogicContracts;
|
||||
using PersonnelDepartmentContracts.SearchModels;
|
||||
using PersonnelDepartmentContracts.StoragesContracts;
|
||||
using PersonnelDepartmentContracts.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PersonnelDepartmentBusinessLogic.BusinessLogics
|
||||
{
|
||||
public class PositionLogic : IPositionLogic
|
||||
{
|
||||
private readonly IPositionStorage _positionStorage;
|
||||
|
||||
public PositionLogic(IPositionStorage positionStorage)
|
||||
{
|
||||
_positionStorage = positionStorage ?? throw new ArgumentNullException(nameof(positionStorage));
|
||||
}
|
||||
|
||||
public bool Create(PositionBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_positionStorage.Insert(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Delete(PositionBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_positionStorage.Delete(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public PositionViewModel? ReadElement(PositionSearchModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
var element = _positionStorage.GetElement(model);
|
||||
if (element == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
public List<PositionViewModel>? ReadList(PositionSearchModel? model)
|
||||
{
|
||||
var list = model == null ? _positionStorage.GetFullList() : _positionStorage.GetFilteredList(model);
|
||||
if (list == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public bool Update(PositionBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_positionStorage.Update(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CheckModel(PositionBindingModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
if (string.IsNullOrEmpty(model.Name))
|
||||
{
|
||||
throw new ArgumentException("Отсутвует имя сотрудника",
|
||||
nameof(model.Name));
|
||||
}
|
||||
if (_positionStorage.GetElement(new PositionSearchModel
|
||||
{
|
||||
Name = model.Name
|
||||
}) != null)
|
||||
{
|
||||
throw new InvalidOperationException("Сотрудник с такими атрибутами уже есть");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
using PersonnelDepartmentContracts.BindingModels;
|
||||
using PersonnelDepartmentContracts.BusinessLogicContracts;
|
||||
using PersonnelDepartmentContracts.SearchModels;
|
||||
using PersonnelDepartmentContracts.StoragesContracts;
|
||||
using PersonnelDepartmentContracts.ViewModels;
|
||||
using PersonnelTypeContracts.StoragesContracts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PersonnelDepartmentBusinessLogic.BusinessLogics
|
||||
{
|
||||
public class TypeLogic : ITypeLogic
|
||||
{
|
||||
private readonly ITypeStorage _typeStorage;
|
||||
|
||||
public TypeLogic(ITypeStorage typeStorage)
|
||||
{
|
||||
_typeStorage = typeStorage ?? throw new ArgumentNullException(nameof(typeStorage));
|
||||
}
|
||||
|
||||
public bool Create(TypeBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_typeStorage.Insert(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Delete(TypeBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_typeStorage.Delete(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public TypeViewModel? ReadElement(TypeSearchModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
var element = _typeStorage.GetElement(model);
|
||||
if (element == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
public List<TypeViewModel>? ReadList(TypeSearchModel? model)
|
||||
{
|
||||
var list = model == null ? _typeStorage.GetFullList() : _typeStorage.GetFilteredList(model);
|
||||
if (list == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public bool Update(TypeBindingModel model)
|
||||
{
|
||||
CheckModel(model);
|
||||
if (_typeStorage.Update(model) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CheckModel(TypeBindingModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
if (string.IsNullOrEmpty(model.Name))
|
||||
{
|
||||
throw new ArgumentException("Отсутвует имя сотрудника",
|
||||
nameof(model.Name));
|
||||
}
|
||||
if (_typeStorage.GetElement(new TypeSearchModel
|
||||
{
|
||||
Name = model.Name
|
||||
}) != null)
|
||||
{
|
||||
throw new InvalidOperationException("Сотрудник с такими атрибутами уже есть");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user