From 206cc0c6fca53412b2774f9fa6ac29c852cc1b39 Mon Sep 17 00:00:00 2001 From: bulatova_karina Date: Sun, 19 May 2024 20:29:10 +0400 Subject: [PATCH] =?UTF-8?q?8=D0=B0=D1=8F=20=D0=BB=D0=B0=D0=B1=D0=B0=20?= =?UTF-8?q?=D0=BD=D0=B0=D0=B4=D0=B5=D1=8E=D1=81=D1=8C=20=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=B0=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BusinessLogics/BackUpLogic.cs | 99 ++++++++++++++++ .../BusinessLogics/OrderLogic.cs | 1 + .../Attributes/ColumnAttribute.cs | 20 ++++ .../Attributes/GridViewAutoSize.cs | 21 ++++ .../BindingModels/BackUpSaveBindingModel.cs | 7 ++ .../BindingModels/MessageInfoBindingModel.cs | 1 + .../BusinessLogicsContracts/IBackUpLogic.cs | 14 +++ .../ComputersShopContracts.csproj | 2 + .../DI/DependencyManager.cs | 62 ++++++++++ .../DI/IDependencyContainer.cs | 40 +++++++ .../DI/IImplementationExtension.cs | 17 +++ .../DI/ServiceDependencyContainer.cs | 62 ++++++++++ .../DI/ServiceProviderLoader.cs | 55 +++++++++ .../DI/UnityDependencyContainer.cs | 38 ++++++ .../StoragesContracts/IBackUpInfo.cs | 8 ++ .../ViewModels/ClientViewModel.cs | 13 ++- .../ViewModels/ComponentViewModel.cs | 8 +- .../ViewModels/ComputerViewModel.cs | 13 ++- .../ViewModels/ImplementerViewModel.cs | 10 +- .../ViewModels/MessageInfoViewModel.cs | 18 ++- .../ViewModels/OrderViewModel.cs | 27 +++-- .../Models/IMessageInfoModel.cs | 2 +- .../ComputerShopDatabase.cs | 2 +- .../ComputersShopDatabaseImplement.csproj | 4 + .../DatabaseImplementationExtension.cs | 22 ++++ .../Implements/BackUpInfo.cs | 33 ++++++ ... 20240519154028_InitialCreate.Designer.cs} | 2 +- ...ate.cs => 20240519154028_InitialCreate.cs} | 0 .../Models/Client.cs | 16 ++- .../Models/Component.cs | 8 +- .../Models/Computer.cs | 28 ++++- .../Models/Implementer.cs | 17 ++- .../Models/MessageInfo.cs | 19 +-- .../Models/Order.cs | 14 ++- .../ComputersShopFileImplement.csproj | 4 + .../FileImplementationExtension.cs | 22 ++++ .../Implements/BackUpInfo.cs | 36 ++++++ .../Models/Client.cs | 21 ++-- .../Models/Component.cs | 18 +-- .../Models/Computer.cs | 44 ++++--- .../Models/Implementer.cs | 7 ++ .../Models/MessageInfo.cs | 20 ++-- .../Models/Order.cs | 11 ++ .../ComputersShopListImplement.csproj | 4 + .../Implements/BackUpInfo.cs | 21 ++++ .../ListImplementationExtension.cs | 27 +++++ .../Models/MessageInfo.cs | 1 + .../DataGridViewExtension.cs | 46 ++++++++ .../ComputersShopView/FormClients.cs | 34 +++--- .../ComputersShopView/FormComponents.cs | 61 +++------- .../ComputersShopView/FormComputer.cs | 60 ++++------ .../ComputersShopView/FormComputers.cs | 32 ++---- .../ComputersShopView/FormImplementers.cs | 42 +++---- ComputersShop/ComputersShopView/FormMails.cs | 9 +- .../ComputersShopView/FormMain.Designer.cs | 24 ++-- ComputersShop/ComputersShopView/FormMain.cs | 108 ++++++++---------- ComputersShop/ComputersShopView/Program.cs | 88 +++++++------- .../ComputersShopContracts.dll | Bin 0 -> 31744 bytes .../ComputersShopDataModels.dll | Bin 0 -> 6144 bytes .../ComputersShopDatabaseImplement.dll | Bin 0 -> 77824 bytes .../ComputersShopFileImplement.dll | Bin 0 -> 40960 bytes .../ComputersShopListImplement.dll | Bin 0 -> 26624 bytes 62 files changed, 1064 insertions(+), 379 deletions(-) create mode 100644 ComputersShop/ComputersShopBusinessLogic/BusinessLogics/BackUpLogic.cs create mode 100644 ComputersShop/ComputersShopContracts/Attributes/ColumnAttribute.cs create mode 100644 ComputersShop/ComputersShopContracts/Attributes/GridViewAutoSize.cs create mode 100644 ComputersShop/ComputersShopContracts/BindingModels/BackUpSaveBindingModel.cs create mode 100644 ComputersShop/ComputersShopContracts/BusinessLogicsContracts/IBackUpLogic.cs create mode 100644 ComputersShop/ComputersShopContracts/DI/DependencyManager.cs create mode 100644 ComputersShop/ComputersShopContracts/DI/IDependencyContainer.cs create mode 100644 ComputersShop/ComputersShopContracts/DI/IImplementationExtension.cs create mode 100644 ComputersShop/ComputersShopContracts/DI/ServiceDependencyContainer.cs create mode 100644 ComputersShop/ComputersShopContracts/DI/ServiceProviderLoader.cs create mode 100644 ComputersShop/ComputersShopContracts/DI/UnityDependencyContainer.cs create mode 100644 ComputersShop/ComputersShopContracts/StoragesContracts/IBackUpInfo.cs create mode 100644 ComputersShop/ComputersShopDatabaseImplement/DatabaseImplementationExtension.cs create mode 100644 ComputersShop/ComputersShopDatabaseImplement/Implements/BackUpInfo.cs rename ComputersShop/ComputersShopDatabaseImplement/Migrations/{20240518091255_InitialCreate.Designer.cs => 20240519154028_InitialCreate.Designer.cs} (99%) rename ComputersShop/ComputersShopDatabaseImplement/Migrations/{20240518091255_InitialCreate.cs => 20240519154028_InitialCreate.cs} (100%) create mode 100644 ComputersShop/ComputersShopFileImplement/FileImplementationExtension.cs create mode 100644 ComputersShop/ComputersShopFileImplement/Implements/BackUpInfo.cs create mode 100644 ComputersShop/ComputersShopListImplement/Implements/BackUpInfo.cs create mode 100644 ComputersShop/ComputersShopListImplement/ListImplementationExtension.cs create mode 100644 ComputersShop/ComputersShopView/DataGridViewExtension.cs create mode 100644 ComputersShop/ImplementationExtensions/ComputersShopContracts.dll create mode 100644 ComputersShop/ImplementationExtensions/ComputersShopDataModels.dll create mode 100644 ComputersShop/ImplementationExtensions/ComputersShopDatabaseImplement.dll create mode 100644 ComputersShop/ImplementationExtensions/ComputersShopFileImplement.dll create mode 100644 ComputersShop/ImplementationExtensions/ComputersShopListImplement.dll diff --git a/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/BackUpLogic.cs b/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/BackUpLogic.cs new file mode 100644 index 0000000..e1659cc --- /dev/null +++ b/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/BackUpLogic.cs @@ -0,0 +1,99 @@ +using ComputersShopContracts.BindingModels; +using ComputersShopContracts.BusinessLogicsContracts; +using ComputersShopContracts.StoragesContracts; +using ComputersShopDataModels; +using Microsoft.Extensions.Logging; +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 ComputersShopBusinessLogic.BusinessLogics +{ + public class BackUpLogic : IBackUpLogic + { + private readonly ILogger _logger; + private readonly IBackUpInfo _backUpInfo; + public BackUpLogic(ILogger logger, IBackUpInfo backUpInfo) + { + _logger = logger; + _backUpInfo = backUpInfo; + } + public void CreateBackUp(BackUpSaveBindingModel model) + { + if (_backUpInfo == null) + { + return; + } + try + { + _logger.LogDebug("Clear folder"); + // зачистка папки и удаление старого архива + var dirInfo = new DirectoryInfo(model.FolderName); + if (dirInfo.Exists) + { + foreach (var file in dirInfo.GetFiles()) + { + file.Delete(); + } + } + _logger.LogDebug("Delete archive"); + string fileName = $"{model.FolderName}.zip"; + if (File.Exists(fileName)) + { + File.Delete(fileName); + } + // берем метод для сохранения + _logger.LogDebug("Get assembly"); + 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); + _logger.LogDebug("Find {count} types", types.Length); + 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}"); + } + _logger.LogDebug("Call SaveToFile method for {name} type", type.Name); + // вызываем метод на выполнение + method?.MakeGenericMethod(modelType).Invoke(this, new object[] { model.FolderName }); + } + } + _logger.LogDebug("Create zip and remove folder"); + // архивируем + ZipFile.CreateFromDirectory(model.FolderName, fileName); + // удаляем папку + dirInfo.Delete(true); + } + catch (Exception) + { + throw; + } + } + private void SaveToFile(string folderName) where T : class, new() + { + var records = _backUpInfo.GetList(); + if (records == null) + { + _logger.LogWarning("{type} type get null list", typeof(T).Name); + return; + } + var jsonFormatter = new DataContractJsonSerializer(typeof(List)); + using var fs = new FileStream(string.Format("{0}/{1}.json", folderName, typeof(T).Name), FileMode.OpenOrCreate); + jsonFormatter.WriteObject(fs, records); + } + } +} diff --git a/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/OrderLogic.cs b/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/OrderLogic.cs index 568118f..e02e660 100644 --- a/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/OrderLogic.cs +++ b/ComputersShop/ComputersShopBusinessLogic/BusinessLogics/OrderLogic.cs @@ -23,6 +23,7 @@ namespace ComputersShopBusinessLogic.BusinessLogics private readonly AbstractMailWorker _mailWorker; static readonly object locker = new(); + public OrderLogic(ILogger logger, IOrderStorage orderStorage, AbstractMailWorker mailWorker) { _logger = logger; diff --git a/ComputersShop/ComputersShopContracts/Attributes/ColumnAttribute.cs b/ComputersShop/ComputersShopContracts/Attributes/ColumnAttribute.cs new file mode 100644 index 0000000..07d5361 --- /dev/null +++ b/ComputersShop/ComputersShopContracts/Attributes/ColumnAttribute.cs @@ -0,0 +1,20 @@ +namespace ComputersShopContracts.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class ColumnAttribute : Attribute + { + public string Title { get; private set; } + public bool Visible { get; private set; } + public int Width { get; private set; } + public GridViewAutoSize GridViewAutoSize { get; private set; } + public bool IsUseAutoSize { get; private set; } + public ColumnAttribute(string title = "", bool visible = true, int width = 0, GridViewAutoSize gridViewAutoSize = GridViewAutoSize.None, bool isUseAutoSize = false) + { + Title = title; + Visible = visible; + Width = width; + GridViewAutoSize = gridViewAutoSize; + IsUseAutoSize = isUseAutoSize; + } + } +} diff --git a/ComputersShop/ComputersShopContracts/Attributes/GridViewAutoSize.cs b/ComputersShop/ComputersShopContracts/Attributes/GridViewAutoSize.cs new file mode 100644 index 0000000..17bd463 --- /dev/null +++ b/ComputersShop/ComputersShopContracts/Attributes/GridViewAutoSize.cs @@ -0,0 +1,21 @@ +namespace ComputersShopContracts.Attributes +{ + public enum GridViewAutoSize + { + NotSet = 0, + + None = 1, + + ColumnHeader = 2, + + AllCellsExceptHeader = 4, + + AllCells = 6, + + DisplayedCellsExceptHeader = 8, + + DisplayedCells = 10, + + Fill = 16 + } +} diff --git a/ComputersShop/ComputersShopContracts/BindingModels/BackUpSaveBindingModel.cs b/ComputersShop/ComputersShopContracts/BindingModels/BackUpSaveBindingModel.cs new file mode 100644 index 0000000..c3d58f1 --- /dev/null +++ b/ComputersShop/ComputersShopContracts/BindingModels/BackUpSaveBindingModel.cs @@ -0,0 +1,7 @@ +namespace ComputersShopContracts.BindingModels +{ + public class BackUpSaveBindingModel + { + public string FolderName { get; set; } = string.Empty; + } +} diff --git a/ComputersShop/ComputersShopContracts/BindingModels/MessageInfoBindingModel.cs b/ComputersShop/ComputersShopContracts/BindingModels/MessageInfoBindingModel.cs index 37eb64c..ab2cbe9 100644 --- a/ComputersShop/ComputersShopContracts/BindingModels/MessageInfoBindingModel.cs +++ b/ComputersShop/ComputersShopContracts/BindingModels/MessageInfoBindingModel.cs @@ -9,6 +9,7 @@ namespace ComputersShopContracts.BindingModels { public class MessageInfoBindingModel : IMessageInfoModel { + public int Id => throw new NotImplementedException(); public string MessageId { get; set; } = string.Empty; public int? ClientId { get; set; } public string SenderName { get; set; } = string.Empty; diff --git a/ComputersShop/ComputersShopContracts/BusinessLogicsContracts/IBackUpLogic.cs b/ComputersShop/ComputersShopContracts/BusinessLogicsContracts/IBackUpLogic.cs new file mode 100644 index 0000000..13b8857 --- /dev/null +++ b/ComputersShop/ComputersShopContracts/BusinessLogicsContracts/IBackUpLogic.cs @@ -0,0 +1,14 @@ +using ComputersShopContracts.BindingModels; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ComputersShopContracts.BusinessLogicsContracts +{ + public interface IBackUpLogic + { + void CreateBackUp(BackUpSaveBindingModel model); + } +} diff --git a/ComputersShop/ComputersShopContracts/ComputersShopContracts.csproj b/ComputersShop/ComputersShopContracts/ComputersShopContracts.csproj index 7ff5503..6aba12b 100644 --- a/ComputersShop/ComputersShopContracts/ComputersShopContracts.csproj +++ b/ComputersShop/ComputersShopContracts/ComputersShopContracts.csproj @@ -13,6 +13,8 @@ + + diff --git a/ComputersShop/ComputersShopContracts/DI/DependencyManager.cs b/ComputersShop/ComputersShopContracts/DI/DependencyManager.cs new file mode 100644 index 0000000..dc6c99f --- /dev/null +++ b/ComputersShop/ComputersShopContracts/DI/DependencyManager.cs @@ -0,0 +1,62 @@ +using Microsoft.Extensions.Logging; + +namespace ComputersShopContracts.DI +{ + public class DependencyManager + { + private readonly IDependencyContainer _dependencyManager; + + private static DependencyManager? _manager; + + private static readonly object _lockObject = new(); + + private DependencyManager() + { + _dependencyManager = new UnityDependencyContainer(); + } + + public static DependencyManager Instance { get { if (_manager == null) { lock (_lockObject) { _manager = new DependencyManager(); } } return _manager; } } + + /// + /// Иницализация библиотек, в которых идут установки зависимостей + /// + public static void InitDependency() + { + var ext = ServiceProviderLoader.GetImplementationExtensions(); + if (ext == null) + { + throw new ArgumentNullException("Отсутствуют компоненты для загрузки зависимостей по модулям"); + } + // регистрируем зависимости + ext.RegisterServices(); + } + + /// + /// Регистрация логгера + /// + /// + public void AddLogging(Action configure) => _dependencyManager.AddLogging(configure); + + /// + /// Добавление зависимости + /// + /// + /// + public void RegisterType(bool isSingle = false) where U : class, T where T : class => _dependencyManager.RegisterType(isSingle); + + /// + /// Добавление зависимости + /// + /// + /// + public void RegisterType(bool isSingle = false) where T : class => _dependencyManager.RegisterType(isSingle); + + /// + /// Получение класса со всеми зависмостями + /// + /// + /// + public T Resolve() => _dependencyManager.Resolve(); + } +} + diff --git a/ComputersShop/ComputersShopContracts/DI/IDependencyContainer.cs b/ComputersShop/ComputersShopContracts/DI/IDependencyContainer.cs new file mode 100644 index 0000000..eb1851f --- /dev/null +++ b/ComputersShop/ComputersShopContracts/DI/IDependencyContainer.cs @@ -0,0 +1,40 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ComputersShopContracts.DI +{ + public interface IDependencyContainer + { + /// + /// Регистрация логгера + /// + /// + void AddLogging(Action configure); + + /// + /// Добавление зависимости + /// + /// + /// + /// + void RegisterType(bool isSingle) where U : class, T where T : class; + + /// + /// Добавление зависимости + /// + /// + /// + void RegisterType(bool isSingle) where T : class; + + /// + /// Получение класса со всеми зависмостями + /// + /// + /// + T Resolve(); + } +} diff --git a/ComputersShop/ComputersShopContracts/DI/IImplementationExtension.cs b/ComputersShop/ComputersShopContracts/DI/IImplementationExtension.cs new file mode 100644 index 0000000..8c84aa7 --- /dev/null +++ b/ComputersShop/ComputersShopContracts/DI/IImplementationExtension.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ComputersShopContracts.DI +{ + public interface IImplementationExtension + { + public int Priority { get; } + /// + /// Регистрация сервисов + /// + public void RegisterServices(); + } +} diff --git a/ComputersShop/ComputersShopContracts/DI/ServiceDependencyContainer.cs b/ComputersShop/ComputersShopContracts/DI/ServiceDependencyContainer.cs new file mode 100644 index 0000000..e20fd65 --- /dev/null +++ b/ComputersShop/ComputersShopContracts/DI/ServiceDependencyContainer.cs @@ -0,0 +1,62 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ComputersShopContracts.DI +{ + public class ServiceDependencyContainer : IDependencyContainer + { + private ServiceProvider? _serviceProvider; + + private readonly ServiceCollection _serviceCollection; + + public ServiceDependencyContainer() + { + _serviceCollection = new ServiceCollection(); + } + + public void AddLogging(Action configure) + { + _serviceCollection.AddLogging(configure); + } + + public void RegisterType(bool isSingle) where U : class, T where T : class + { + if (isSingle) + { + _serviceCollection.AddSingleton(); + } + else + { + _serviceCollection.AddTransient(); + } + _serviceProvider = null; + } + + public void RegisterType(bool isSingle) where T : class + { + if (isSingle) + { + _serviceCollection.AddSingleton(); + } + else + { + _serviceCollection.AddTransient(); + } + _serviceProvider = null; + } + + public T Resolve() + { + if (_serviceProvider == null) + { + _serviceProvider = _serviceCollection.BuildServiceProvider(); + } + return _serviceProvider.GetService()!; + } + } +} diff --git a/ComputersShop/ComputersShopContracts/DI/ServiceProviderLoader.cs b/ComputersShop/ComputersShopContracts/DI/ServiceProviderLoader.cs new file mode 100644 index 0000000..5ea7686 --- /dev/null +++ b/ComputersShop/ComputersShopContracts/DI/ServiceProviderLoader.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace ComputersShopContracts.DI +{ + public class ServiceProviderLoader + { + /// + /// Загрузка всех классов-реализаций IImplementationExtension + /// + /// + public static IImplementationExtension? GetImplementationExtensions() + { + IImplementationExtension? source = null; + var files = Directory.GetFiles(TryGetImplementationExtensionsFolder(), "*.dll", SearchOption.AllDirectories); + foreach (var file in files.Distinct()) + { + Assembly asm = Assembly.LoadFrom(file); + foreach (var t in asm.GetExportedTypes()) + { + if (t.IsClass && typeof(IImplementationExtension).IsAssignableFrom(t)) + { + if (source == null) + { + source = (IImplementationExtension)Activator.CreateInstance(t)!; + } + else + { + var newSource = (IImplementationExtension)Activator.CreateInstance(t)!; + if (newSource.Priority > source.Priority) + { + source = newSource; + } + } + } + } + } + return source; + } + + private static string TryGetImplementationExtensionsFolder() + { + var directory = new DirectoryInfo(Directory.GetCurrentDirectory()); + while (directory != null && !directory.GetDirectories("ImplementationExtensions", SearchOption.AllDirectories).Any(x => x.Name == "ImplementationExtensions")) + { + directory = directory.Parent; + } + return $"{directory?.FullName}\\ImplementationExtensions"; + } + } +} diff --git a/ComputersShop/ComputersShopContracts/DI/UnityDependencyContainer.cs b/ComputersShop/ComputersShopContracts/DI/UnityDependencyContainer.cs new file mode 100644 index 0000000..d66beae --- /dev/null +++ b/ComputersShop/ComputersShopContracts/DI/UnityDependencyContainer.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.Logging; +using Unity.Microsoft.Logging; +using Unity; + + +namespace ComputersShopContracts.DI +{ + public class UnityDependencyContainer : IDependencyContainer + { + private readonly IUnityContainer _container; + + public UnityDependencyContainer() + { + _container = new UnityContainer(); + } + + public void AddLogging(Action configure) + { + var factory = LoggerFactory.Create(configure); + _container.AddExtension(new LoggingExtension(factory)); + } + + public void RegisterType(bool isSingle) where U : class, T where T : class + { + _container.RegisterType(isSingle ? TypeLifetime.Singleton : TypeLifetime.Transient); + } + + public void RegisterType(bool isSingle) where T : class + { + _container.RegisterType(isSingle ? TypeLifetime.Singleton : TypeLifetime.Transient); + } + + public T Resolve() + { + return _container.Resolve(); + } + } +} diff --git a/ComputersShop/ComputersShopContracts/StoragesContracts/IBackUpInfo.cs b/ComputersShop/ComputersShopContracts/StoragesContracts/IBackUpInfo.cs new file mode 100644 index 0000000..4340ec2 --- /dev/null +++ b/ComputersShop/ComputersShopContracts/StoragesContracts/IBackUpInfo.cs @@ -0,0 +1,8 @@ +namespace ComputersShopContracts.StoragesContracts +{ + public interface IBackUpInfo + { + List? GetList() where T : class, new(); + Type? GetTypeByModelInterface(string modelInterfaceName); + } +} diff --git a/ComputersShop/ComputersShopContracts/ViewModels/ClientViewModel.cs b/ComputersShop/ComputersShopContracts/ViewModels/ClientViewModel.cs index 27ea807..1cab0a6 100644 --- a/ComputersShop/ComputersShopContracts/ViewModels/ClientViewModel.cs +++ b/ComputersShop/ComputersShopContracts/ViewModels/ClientViewModel.cs @@ -1,4 +1,5 @@ -using ComputersShopDataModels.Models; +using ComputersShopContracts.Attributes; +using ComputersShopDataModels.Models; using System; using System.Collections.Generic; using System.ComponentModel; @@ -10,12 +11,16 @@ namespace ComputersShopContracts.ViewModels { public class ClientViewModel : IClientModel { + [Column(visible: false)] public int Id { get; set; } - [DisplayName("ФИО клиента")] + + [Column(title: "ФИО клиента", width: 150)] public string ClientFIO { get; set; } = string.Empty; - [DisplayName("Логин (эл. почта)")] + + [Column(title: "Логин (эл. почта)", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string Email { get; set; } = string.Empty; - [DisplayName("Пароль")] + + [Column(title: "Пароль", width: 150)] public string Password { get; set; } = string.Empty; } } diff --git a/ComputersShop/ComputersShopContracts/ViewModels/ComponentViewModel.cs b/ComputersShop/ComputersShopContracts/ViewModels/ComponentViewModel.cs index dc4627a..29e1955 100644 --- a/ComputersShop/ComputersShopContracts/ViewModels/ComponentViewModel.cs +++ b/ComputersShop/ComputersShopContracts/ViewModels/ComponentViewModel.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using ComputersShopDataModels.Models; +using ComputersShopContracts.Attributes; using System.ComponentModel; @@ -11,10 +12,13 @@ namespace ComputersShopContracts.ViewModels { public class ComponentViewModel : IComponentModel { + [Column(visible: false)] public int Id { get; set; } - [DisplayName("Название компонента")] + + [Column(title: "Название компонента", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string ComponentName { get; set; } = string.Empty; - [DisplayName("Цена")] + + [Column(title: "Цена", width: 150)] public double Cost { get; set; } } } diff --git a/ComputersShop/ComputersShopContracts/ViewModels/ComputerViewModel.cs b/ComputersShop/ComputersShopContracts/ViewModels/ComputerViewModel.cs index b75fe37..c6a5df5 100644 --- a/ComputersShop/ComputersShopContracts/ViewModels/ComputerViewModel.cs +++ b/ComputersShop/ComputersShopContracts/ViewModels/ComputerViewModel.cs @@ -4,20 +4,27 @@ using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; +using ComputersShopContracts.Attributes; using ComputersShopDataModels.Models; namespace ComputersShopContracts.ViewModels { public class ComputerViewModel : IComputerModel { + [Column(visible: false)] public int Id { get; set; } - [DisplayName("Название компьютера")] + [Column(title: "Название компьютера", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string ComputerName { get; set; } = string.Empty; - [DisplayName("Цена")] + [Column(title: "Цена", width: 150)] public double Price { get; set; } - public Dictionary ComputerComponents { get; set; } = new(); + [Column(visible: false)] + public Dictionary ComputerComponents + { + get; + set; + } = new(); } } \ No newline at end of file diff --git a/ComputersShop/ComputersShopContracts/ViewModels/ImplementerViewModel.cs b/ComputersShop/ComputersShopContracts/ViewModels/ImplementerViewModel.cs index 030ad35..9cbac18 100644 --- a/ComputersShop/ComputersShopContracts/ViewModels/ImplementerViewModel.cs +++ b/ComputersShop/ComputersShopContracts/ViewModels/ImplementerViewModel.cs @@ -4,24 +4,26 @@ using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; +using ComputersShopContracts.Attributes; using ComputersShopDataModels.Models; namespace ComputersShopContracts.ViewModels { public class ImplementerViewModel { + [Column(visible: false)] public int Id { get; set; } - [DisplayName("ФИО исполнителя")] + [Column(title: "ФИО исполнителя", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string ImplementerFIO { get; set; } = string.Empty; - [DisplayName("Пароль")] + [Column(title: "Пароль", width: 100)] public string Password { get; set; } = string.Empty; - [DisplayName("Стаж работы")] + [Column(title: "Стаж работы", width: 100)] public int WorkExperience { get; set; } - [DisplayName("Квалификация")] + [Column(title: "Квалификация", width: 100)] public int Qualification { get; set; } } } diff --git a/ComputersShop/ComputersShopContracts/ViewModels/MessageInfoViewModel.cs b/ComputersShop/ComputersShopContracts/ViewModels/MessageInfoViewModel.cs index cf1de86..3d182b6 100644 --- a/ComputersShop/ComputersShopContracts/ViewModels/MessageInfoViewModel.cs +++ b/ComputersShop/ComputersShopContracts/ViewModels/MessageInfoViewModel.cs @@ -1,4 +1,6 @@ -using System; +using ComputersShopContracts.Attributes; +using ComputersShopDataModels.Models; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; @@ -9,19 +11,25 @@ namespace ComputersShopContracts.ViewModels { public class MessageInfoViewModel { + [Column(visible: false)] + public int Id { get; set; } + + [Column(visible: false)] public string MessageId { get; set; } = string.Empty; + + [Column(visible: false)] public int? ClientId { get; set; } - [DisplayName("Отправитель")] + [Column(title: "Отправитель", width: 150)] public string SenderName { get; set; } = string.Empty; - [DisplayName("Дата письма")] + [Column(title: "Дата письма", width: 120)] public DateTime DateDelivery { get; set; } - [DisplayName("Заголовок")] + [Column(title: "Дата письма", width: 150)] public string Subject { get; set; } = string.Empty; - [DisplayName("Текст")] + [Column(title: "Текст", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string Body { get; set; } = string.Empty; } } diff --git a/ComputersShop/ComputersShopContracts/ViewModels/OrderViewModel.cs b/ComputersShop/ComputersShopContracts/ViewModels/OrderViewModel.cs index b823472..a98a07a 100644 --- a/ComputersShop/ComputersShopContracts/ViewModels/OrderViewModel.cs +++ b/ComputersShop/ComputersShopContracts/ViewModels/OrderViewModel.cs @@ -1,4 +1,5 @@ -using ComputersShopDataModels.Enums; +using ComputersShopContracts.Attributes; +using ComputersShopDataModels.Enums; using ComputersShopDataModels.Models; using System; using System.Collections.Generic; @@ -11,39 +12,43 @@ namespace ComputersShopContracts.ViewModels { public class OrderViewModel : IOrderModel { - [DisplayName("Номер")] + [Column(title: "Номер", width: 100)] public int Id { get; set; } + [Column(visible: false)] public int ComputerId { get; set; } - [DisplayName("Компьютер")] + [Column(title: "Компьютеры", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string ComputerName { get; set; } = string.Empty; + [Column(visible: false)] public int ClientId { get; set; } - [DisplayName("ФИО клиента")] + [Column(title: "ФИО клиента", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string ClientFIO { get; set; } = string.Empty; + [Column(visible: false)] public string ClientEmail { get; set; } = string.Empty; + [Column(visible: false)] public int? ImplementerId { get; set; } - [DisplayName("ФИО исполнителя")] + [Column(title: "ФИО исполнителя", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string ImplementerFIO { get; set; } = string.Empty; - [DisplayName("Количество")] + [Column(title: "Количество", width: 100)] public int Count { get; set; } - [DisplayName("Сумма")] + [Column(title: "Сумма", width: 120)] public double Sum { get; set; } - [DisplayName("Статус")] + [Column(title: "Статус", width: 100)] public OrderStatus Status { get; set; } = OrderStatus.Неизвестен; - [DisplayName("Дата создания")] + [Column(title: "Дата создания", width: 120)] public DateTime DateCreate { get; set; } = DateTime.Now; - [DisplayName("Дата выполнения")] + [Column(title: "Дата выполнения", width: 120)] public DateTime? DateImplement { get; set; } } -} \ No newline at end of file +} diff --git a/ComputersShop/ComputersShopDataModels/Models/IMessageInfoModel.cs b/ComputersShop/ComputersShopDataModels/Models/IMessageInfoModel.cs index aa325ce..bed34e1 100644 --- a/ComputersShop/ComputersShopDataModels/Models/IMessageInfoModel.cs +++ b/ComputersShop/ComputersShopDataModels/Models/IMessageInfoModel.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace ComputersShopDataModels.Models { - public interface IMessageInfoModel + public interface IMessageInfoModel : IId { string MessageId { get; } int? ClientId { get; } diff --git a/ComputersShop/ComputersShopDatabaseImplement/ComputerShopDatabase.cs b/ComputersShop/ComputersShopDatabaseImplement/ComputerShopDatabase.cs index 7d7d0dc..3e6d6a7 100644 --- a/ComputersShop/ComputersShopDatabaseImplement/ComputerShopDatabase.cs +++ b/ComputersShop/ComputersShopDatabaseImplement/ComputerShopDatabase.cs @@ -15,7 +15,7 @@ namespace ComputersShopDatabaseImplement { if (optionsBuilder.IsConfigured == false) { - optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-1DE5E8N\SQLEXPRESS;Initial Catalog=ComputersShopDatabaseNew; + optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-1DE5E8N\SQLEXPRESS;Initial Catalog=ComputersShopDatabaseNew8; Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True"); } base.OnConfiguring(optionsBuilder); diff --git a/ComputersShop/ComputersShopDatabaseImplement/ComputersShopDatabaseImplement.csproj b/ComputersShop/ComputersShopDatabaseImplement/ComputersShopDatabaseImplement.csproj index dec845d..03560bc 100644 --- a/ComputersShop/ComputersShopDatabaseImplement/ComputersShopDatabaseImplement.csproj +++ b/ComputersShop/ComputersShopDatabaseImplement/ComputersShopDatabaseImplement.csproj @@ -20,4 +20,8 @@ + + + + diff --git a/ComputersShop/ComputersShopDatabaseImplement/DatabaseImplementationExtension.cs b/ComputersShop/ComputersShopDatabaseImplement/DatabaseImplementationExtension.cs new file mode 100644 index 0000000..7815e03 --- /dev/null +++ b/ComputersShop/ComputersShopDatabaseImplement/DatabaseImplementationExtension.cs @@ -0,0 +1,22 @@ +using ComputersShopContracts.DI; +using ComputersShopContracts.StoragesContracts; +using ComputersShopDatabaseImplement.Implements; + +namespace ComputersShopDatabaseImplement +{ + public class DatabaseImplementationExtension : IImplementationExtension + { + public int Priority => 2; + + public void RegisterServices() + { + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + } + } +} diff --git a/ComputersShop/ComputersShopDatabaseImplement/Implements/BackUpInfo.cs b/ComputersShop/ComputersShopDatabaseImplement/Implements/BackUpInfo.cs new file mode 100644 index 0000000..b3a4097 --- /dev/null +++ b/ComputersShop/ComputersShopDatabaseImplement/Implements/BackUpInfo.cs @@ -0,0 +1,33 @@ +using ComputersShopContracts.StoragesContracts; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ComputersShopDatabaseImplement.Implements +{ + public class BackUpInfo : IBackUpInfo + { + public List? GetList() where T : class, new() + { + using var context = new ComputersShopDatabase(); + return context.Set().ToList(); + } + + public Type? GetTypeByModelInterface(string modelInterfaceName) + { + var assembly = typeof(BackUpInfo).Assembly; + var types = assembly.GetTypes(); + foreach (var type in types) + { + if (type.IsClass && type.GetInterface(modelInterfaceName) != null) + { + return type; + } + } + return null; + } + } +} + diff --git a/ComputersShop/ComputersShopDatabaseImplement/Migrations/20240518091255_InitialCreate.Designer.cs b/ComputersShop/ComputersShopDatabaseImplement/Migrations/20240519154028_InitialCreate.Designer.cs similarity index 99% rename from ComputersShop/ComputersShopDatabaseImplement/Migrations/20240518091255_InitialCreate.Designer.cs rename to ComputersShop/ComputersShopDatabaseImplement/Migrations/20240519154028_InitialCreate.Designer.cs index a999074..3e4f5fd 100644 --- a/ComputersShop/ComputersShopDatabaseImplement/Migrations/20240518091255_InitialCreate.Designer.cs +++ b/ComputersShop/ComputersShopDatabaseImplement/Migrations/20240519154028_InitialCreate.Designer.cs @@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace ComputersShopDatabaseImplement.Migrations { [DbContext(typeof(ComputersShopDatabase))] - [Migration("20240518091255_InitialCreate")] + [Migration("20240519154028_InitialCreate")] partial class InitialCreate { /// diff --git a/ComputersShop/ComputersShopDatabaseImplement/Migrations/20240518091255_InitialCreate.cs b/ComputersShop/ComputersShopDatabaseImplement/Migrations/20240519154028_InitialCreate.cs similarity index 100% rename from ComputersShop/ComputersShopDatabaseImplement/Migrations/20240518091255_InitialCreate.cs rename to ComputersShop/ComputersShopDatabaseImplement/Migrations/20240519154028_InitialCreate.cs diff --git a/ComputersShop/ComputersShopDatabaseImplement/Models/Client.cs b/ComputersShop/ComputersShopDatabaseImplement/Models/Client.cs index c50ff57..22edb71 100644 --- a/ComputersShop/ComputersShopDatabaseImplement/Models/Client.cs +++ b/ComputersShop/ComputersShopDatabaseImplement/Models/Client.cs @@ -8,28 +8,28 @@ using System.Threading.Tasks; using ComputersShopContracts.BindingModels; using ComputersShopContracts.ViewModels; using ComputersShopDataModels.Models; +using System.Runtime.Serialization; namespace ComputersShopDatabaseImplement.Models { + [DataContract] public class Client : IClientModel { + [DataMember] public int Id { get; private set; } - + [DataMember] [Required] public string ClientFIO { get; private set; } = string.Empty; - + [DataMember] [Required] public string Email { get; private set; } = string.Empty; - + [DataMember] [Required] public string Password { get; private set; } = string.Empty; - [ForeignKey("ClientId")] public virtual List Orders { get; set; } = new(); - [ForeignKey("ClientId")] public virtual List ClientMessages { get; set; } = new(); - public static Client? Create(ClientBindingModel model) { if (model == null) @@ -44,7 +44,6 @@ namespace ComputersShopDatabaseImplement.Models Password = model.Password }; } - public void Update(ClientBindingModel model) { if (model == null) @@ -55,7 +54,6 @@ namespace ComputersShopDatabaseImplement.Models Email = model.Email; Password = model.Password; } - public ClientViewModel GetViewModel => new() { Id = Id, @@ -64,4 +62,4 @@ namespace ComputersShopDatabaseImplement.Models Password = Password }; } -} \ No newline at end of file +} diff --git a/ComputersShop/ComputersShopDatabaseImplement/Models/Component.cs b/ComputersShop/ComputersShopDatabaseImplement/Models/Component.cs index 0f7d27c..b9432f9 100644 --- a/ComputersShop/ComputersShopDatabaseImplement/Models/Component.cs +++ b/ComputersShop/ComputersShopDatabaseImplement/Models/Component.cs @@ -8,14 +8,19 @@ using ComputersShopContracts.ViewModels; using ComputersShopDataModels.Models; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.Serialization; namespace ComputersShopDatabaseImplement.Models { + [DataContract] public class Component : IComponentModel { + [DataMember] public int Id { get; private set; } + [DataMember] [Required] public string ComponentName { get; private set; } = string.Empty; + [DataMember] [Required] public double Cost { get; set; } [ForeignKey("ComponentId")] @@ -30,7 +35,7 @@ namespace ComputersShopDatabaseImplement.Models { Id = model.Id, ComponentName = model.ComponentName, - Cost = model.Cost, + Cost = model.Cost }; } public static Component Create(ComponentViewModel model) @@ -59,3 +64,4 @@ namespace ComputersShopDatabaseImplement.Models }; } } + diff --git a/ComputersShop/ComputersShopDatabaseImplement/Models/Computer.cs b/ComputersShop/ComputersShopDatabaseImplement/Models/Computer.cs index b6410ad..bab17a8 100644 --- a/ComputersShop/ComputersShopDatabaseImplement/Models/Computer.cs +++ b/ComputersShop/ComputersShopDatabaseImplement/Models/Computer.cs @@ -8,17 +8,27 @@ using ComputersShopContracts.BindingModels; using ComputersShopContracts.ViewModels; using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; namespace ComputersShopDatabaseImplement.Models { + [DataContract] public class Computer : IComputerModel { + [DataMember] public int Id { get; set; } + + [DataMember] [Required] public string ComputerName { get; set; } = string.Empty; + + [DataMember] [Required] public double Price { get; set; } + private Dictionary? _computerComponents = null; + + [DataMember] [NotMapped] public Dictionary ComputerComponents { @@ -26,16 +36,19 @@ namespace ComputersShopDatabaseImplement.Models { if (_computerComponents == null) { - _computerComponents = Components.ToDictionary(recPC => recPC.ComponentId, recPC => - (recPC.Component as IComponentModel, recPC.Count)); + _computerComponents = Components + .ToDictionary(recPC => recPC.ComponentId, recPC => (recPC.Component as IComponentModel, recPC.Count)); } return _computerComponents; } } + [ForeignKey("ComputerId")] public virtual List Components { get; set; } = new(); + [ForeignKey("ComputerId")] public virtual List Orders { get; set; } = new(); + public static Computer Create(ComputersShopDatabase context, ComputerBindingModel model) { return new Computer() @@ -50,11 +63,13 @@ namespace ComputersShopDatabaseImplement.Models }).ToList() }; } + public void Update(ComputerBindingModel model) { ComputerName = model.ComputerName; Price = model.Price; } + public ComputerViewModel GetViewModel => new() { Id = Id, @@ -62,11 +77,12 @@ namespace ComputersShopDatabaseImplement.Models Price = Price, ComputerComponents = ComputerComponents }; + public void UpdateComponents(ComputersShopDatabase context, ComputerBindingModel model) { var computerComponents = context.ComputerComponents.Where(rec => rec.ComputerId == model.Id).ToList(); if (computerComponents != null && computerComponents.Count > 0) - { // удалили те, которых нет в модели + { // удалили те, которых нет в модели context.ComputerComponents.RemoveRange(computerComponents.Where(rec => !model.ComputerComponents.ContainsKey(rec.ComponentId))); context.SaveChanges(); // обновили количество у существующих записей @@ -78,13 +94,13 @@ namespace ComputersShopDatabaseImplement.Models context.SaveChanges(); } var computer = context.Computers.First(x => x.Id == Id); - foreach (var pc in model.ComputerComponents) + foreach (var ic in model.ComputerComponents) { context.ComputerComponents.Add(new ComputerComponent { Computer = computer, - Component = context.Components.First(x => x.Id == pc.Key), - Count = pc.Value.Item2 + Component = context.Components.First(x => x.Id == ic.Key), + Count = ic.Value.Item2 }); context.SaveChanges(); } diff --git a/ComputersShop/ComputersShopDatabaseImplement/Models/Implementer.cs b/ComputersShop/ComputersShopDatabaseImplement/Models/Implementer.cs index 740d726..582b49b 100644 --- a/ComputersShop/ComputersShopDatabaseImplement/Models/Implementer.cs +++ b/ComputersShop/ComputersShopDatabaseImplement/Models/Implementer.cs @@ -8,28 +8,29 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using ComputersShopDataModels.Models; +using System.Runtime.Serialization; namespace ComputersShopDatabaseImplement.Models { + [DataContract] public class Implementer : IImplementerModel { + [DataMember] public int Id { get; set; } - + [DataMember] [Required] public string ImplementerFIO { get; set; } = string.Empty; - + [DataMember] [Required] public string Password { get; set; } = string.Empty; - + [DataMember] [Required] public int WorkExperience { get; set; } - + [DataMember] [Required] public int Qualification { get; set; } - [ForeignKey("ImplementerId")] public virtual List Orders { get; set; } = new(); - public static Implementer? Create(ImplementerBindingModel model) { if (model == null) @@ -45,7 +46,6 @@ namespace ComputersShopDatabaseImplement.Models Qualification = model.Qualification }; } - public static Implementer Create(ImplementerViewModel model) { return new Implementer @@ -57,7 +57,6 @@ namespace ComputersShopDatabaseImplement.Models Qualification = model.Qualification }; } - public void Update(ImplementerBindingModel model) { if (model == null) @@ -69,7 +68,6 @@ namespace ComputersShopDatabaseImplement.Models WorkExperience = model.WorkExperience; Qualification = model.Qualification; } - public ImplementerViewModel GetViewModel => new() { Id = Id, @@ -80,3 +78,4 @@ namespace ComputersShopDatabaseImplement.Models }; } } + diff --git a/ComputersShop/ComputersShopDatabaseImplement/Models/MessageInfo.cs b/ComputersShop/ComputersShopDatabaseImplement/Models/MessageInfo.cs index 1349d0b..a2dcc14 100644 --- a/ComputersShop/ComputersShopDatabaseImplement/Models/MessageInfo.cs +++ b/ComputersShop/ComputersShopDatabaseImplement/Models/MessageInfo.cs @@ -8,31 +8,35 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Runtime.Serialization; namespace ComputersShopDatabaseImplement.Models { - public class MessageInfo : IMessageInfoModel + [DataContract] + public class MessageInfo : IMessageInfoModel { + [NotMapped] + public int Id { get; private set; } + [DataMember] [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] public string MessageId { get; set; } = string.Empty; - + [DataMember] public int? ClientId { get; set; } - + [DataMember] [Required] public string SenderName { get; set; } = string.Empty; - + [DataMember] [Required] public DateTime DateDelivery { get; set; } + [DataMember] [Required] public string Subject { get; set; } = string.Empty; - + [DataMember] [Required] public string Body { get; set; } = string.Empty; - public virtual Client? Client { get; set; } - public static MessageInfo? Create(MessageInfoBindingModel? model) { if (model == null) @@ -49,7 +53,6 @@ namespace ComputersShopDatabaseImplement.Models Body = model.Body }; } - public MessageInfoViewModel GetViewModel => new() { MessageId = MessageId, diff --git a/ComputersShop/ComputersShopDatabaseImplement/Models/Order.cs b/ComputersShop/ComputersShopDatabaseImplement/Models/Order.cs index efa255f..d9ade76 100644 --- a/ComputersShop/ComputersShopDatabaseImplement/Models/Order.cs +++ b/ComputersShop/ComputersShopDatabaseImplement/Models/Order.cs @@ -2,38 +2,50 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; using ComputersShopContracts.BindingModels; using ComputersShopContracts.ViewModels; using ComputersShopDataModels.Enums; +using ComputersShopDataModels.Models; namespace ComputersShopDatabaseImplement.Models { - public class Order + [DataContract] + public class Order : IOrderModel { + [DataMember] public int Id { get; set; } + [DataMember] [Required] public int ComputerId { get; set; } + [DataMember] [Required] public int ClientId { get; set; } + [DataMember] public int? ImplementerId { get; private set; } + [DataMember] [Required] public int Count { get; set; } + [DataMember] [Required] public double Sum { get; set; } + [DataMember] [Required] public OrderStatus Status { get; set; } + [DataMember] [Required] public DateTime DateCreate { get; set; } + [DataMember] public DateTime? DateImplement { get; set; } public virtual Computer Computer { get; set; } diff --git a/ComputersShop/ComputersShopFileImplement/ComputersShopFileImplement.csproj b/ComputersShop/ComputersShopFileImplement/ComputersShopFileImplement.csproj index 8eb14fb..fa6e324 100644 --- a/ComputersShop/ComputersShopFileImplement/ComputersShopFileImplement.csproj +++ b/ComputersShop/ComputersShopFileImplement/ComputersShopFileImplement.csproj @@ -11,4 +11,8 @@ + + + + diff --git a/ComputersShop/ComputersShopFileImplement/FileImplementationExtension.cs b/ComputersShop/ComputersShopFileImplement/FileImplementationExtension.cs new file mode 100644 index 0000000..62a4623 --- /dev/null +++ b/ComputersShop/ComputersShopFileImplement/FileImplementationExtension.cs @@ -0,0 +1,22 @@ +using ComputersShopContracts.DI; +using ComputersShopContracts.StoragesContracts; +using ComputersShopFileImplement.Implements; + +namespace ComputersShopFileImplement +{ + public class FileImplementationExtension : IImplementationExtension + { + public int Priority => 1; + + public void RegisterServices() + { + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + } + } +} diff --git a/ComputersShop/ComputersShopFileImplement/Implements/BackUpInfo.cs b/ComputersShop/ComputersShopFileImplement/Implements/BackUpInfo.cs new file mode 100644 index 0000000..fb07eff --- /dev/null +++ b/ComputersShop/ComputersShopFileImplement/Implements/BackUpInfo.cs @@ -0,0 +1,36 @@ +using ComputersShopContracts.StoragesContracts; +using System.Reflection; + +namespace ComputersShopFileImplement.Implements +{ + public class BackUpInfo : IBackUpInfo + { + private readonly DataFileSingleton source; + + public BackUpInfo() + { + source = DataFileSingleton.GetInstance(); + } + + public List? GetList() where T : class, new() + { + return (List?)source.GetType().GetProperties() + .FirstOrDefault(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericArguments()[0] == typeof(T)) + ?.GetValue(source); + } + + public Type? GetTypeByModelInterface(string modelInterfaceName) + { + var assembly = typeof(BackUpInfo).Assembly; + var types = assembly.GetTypes(); + foreach (var type in types) + { + if (type.IsClass && type.GetInterface(modelInterfaceName) != null) + { + return type; + } + } + return null; + } + } +} diff --git a/ComputersShop/ComputersShopFileImplement/Models/Client.cs b/ComputersShop/ComputersShopFileImplement/Models/Client.cs index b06e3f0..334c12b 100644 --- a/ComputersShop/ComputersShopFileImplement/Models/Client.cs +++ b/ComputersShop/ComputersShopFileImplement/Models/Client.cs @@ -1,19 +1,26 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; using ComputersShopContracts.BindingModels; using ComputersShopContracts.ViewModels; +using ComputersShopDataModels.Models; namespace ComputersShopFileImplement.Models { - public class Client + [DataContract] + public class Client : IClientModel { + [DataMember] public int Id { get; private set; } + [DataMember] public string ClientFIO { get; private set; } = string.Empty; + [DataMember] public string Email { get; private set; } = string.Empty; + [DataMember] public string Password { get; private set; } = string.Empty; public static Client? Create(ClientBindingModel model) { @@ -21,12 +28,12 @@ namespace ComputersShopFileImplement.Models { return null; } - return new Client() + return new() { Id = model.Id, ClientFIO = model.ClientFIO, Email = model.Email, - Password = model.Password, + Password = model.Password }; } public static Client? Create(XElement element) @@ -35,12 +42,12 @@ namespace ComputersShopFileImplement.Models { return null; } - return new Client() + return new() { Id = Convert.ToInt32(element.Attribute("Id")!.Value), - ClientFIO = element.Element("ClientFIO")!.Value, + ClientFIO = element.Element("FIO")!.Value, Email = element.Element("Email")!.Value, - Password = element.Element("Password")!.Value, + Password = element.Element("Password")!.Value }; } public void Update(ClientBindingModel model) @@ -62,7 +69,7 @@ namespace ComputersShopFileImplement.Models }; public XElement GetXElement => new("Client", new XAttribute("Id", Id), - new XElement("ClientFIO", ClientFIO), + new XElement("FIO", ClientFIO), new XElement("Email", Email), new XElement("Password", Password) ); diff --git a/ComputersShop/ComputersShopFileImplement/Models/Component.cs b/ComputersShop/ComputersShopFileImplement/Models/Component.cs index 52a5e3c..0594305 100644 --- a/ComputersShop/ComputersShopFileImplement/Models/Component.cs +++ b/ComputersShop/ComputersShopFileImplement/Models/Component.cs @@ -1,20 +1,20 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using ComputersShopContracts.BindingModels; +using ComputersShopContracts.BindingModels; using ComputersShopContracts.ViewModels; using ComputersShopDataModels.Models; +using System.Runtime.Serialization; using System.Xml.Linq; namespace ComputersShopFileImplement.Models { + [DataContract] public class Component : IComponentModel { + [DataMember] public int Id { get; private set; } + [DataMember] public string ComponentName { get; private set; } = string.Empty; + [DataMember] public double Cost { get; set; } public static Component? Create(ComponentBindingModel model) { @@ -58,8 +58,8 @@ namespace ComputersShopFileImplement.Models Cost = Cost }; public XElement GetXElement => new("Component", - new XAttribute("Id", Id), - new XElement("ComponentName", ComponentName), - new XElement("Cost", Cost.ToString())); + new XAttribute("Id", Id), + new XElement("ComponentName", ComponentName), + new XElement("Cost", Cost.ToString())); } } diff --git a/ComputersShop/ComputersShopFileImplement/Models/Computer.cs b/ComputersShop/ComputersShopFileImplement/Models/Computer.cs index afaa4d9..a1321c9 100644 --- a/ComputersShop/ComputersShopFileImplement/Models/Computer.cs +++ b/ComputersShop/ComputersShopFileImplement/Models/Computer.cs @@ -7,16 +7,27 @@ using ComputersShopContracts.BindingModels; using ComputersShopContracts.ViewModels; using ComputersShopDataModels.Models; using System.Xml.Linq; +using System.Runtime.Serialization; namespace ComputersShopFileImplement.Models { + [DataContract] public class Computer : IComputerModel { + [DataMember] public int Id { get; private set; } + + [DataMember] public string ComputerName { get; private set; } = string.Empty; + + [DataMember] public double Price { get; private set; } + public Dictionary Components { get; private set; } = new(); + private Dictionary? _computerComponents = null; + + [DataMember] public Dictionary ComputerComponents { get @@ -24,14 +35,14 @@ namespace ComputersShopFileImplement.Models if (_computerComponents == null) { var source = DataFileSingleton.GetInstance(); - _computerComponents = Components.ToDictionary(x => x.Key, y => - ((source.Components.FirstOrDefault(z => z.Id == y.Key) as IComponentModel)!, - y.Value)); + _computerComponents = Components.ToDictionary(x => x.Key, + y => ((source.Components.FirstOrDefault(z => z.Id == y.Key) as IComponentModel)!, y.Value)); } return _computerComponents; } } - public static Computer? Create(ComputerBindingModel model) + + public static Computer? Create(ComputerBindingModel? model) { if (model == null) { @@ -45,6 +56,7 @@ namespace ComputersShopFileImplement.Models Components = model.ComputerComponents.ToDictionary(x => x.Key, x => x.Value.Item2) }; } + public static Computer? Create(XElement element) { if (element == null) @@ -56,14 +68,12 @@ namespace ComputersShopFileImplement.Models Id = Convert.ToInt32(element.Attribute("Id")!.Value), ComputerName = element.Element("ComputerName")!.Value, Price = Convert.ToDouble(element.Element("Price")!.Value), - Components = - element.Element("ComputerComponents")!.Elements("ComputerComponent") - .ToDictionary(x => - Convert.ToInt32(x.Element("Key")?.Value), x => - Convert.ToInt32(x.Element("Value")?.Value)) + Components = element.Element("ComputerComponents")!.Elements("ComputerComponent") + .ToDictionary(x => Convert.ToInt32(x.Element("Key")?.Value), x => Convert.ToInt32(x.Element("Value")?.Value)) }; } - public void Update(ComputerBindingModel model) + + public void Update(ComputerBindingModel? model) { if (model == null) { @@ -74,6 +84,7 @@ namespace ComputersShopFileImplement.Models Components = model.ComputerComponents.ToDictionary(x => x.Key, x => x.Value.Item2); _computerComponents = null; } + public ComputerViewModel GetViewModel => new() { Id = Id, @@ -81,13 +92,14 @@ namespace ComputersShopFileImplement.Models Price = Price, ComputerComponents = ComputerComponents }; + public XElement GetXElement => new("Computer", - new XAttribute("Id", Id), - new XElement("ComputerName", ComputerName), - new XElement("Price", Price.ToString()), - new XElement("ComputerComponents", Components.Select(x => - new XElement("ComputerComponent", new XElement("Key", x.Key), - new XElement("Value", x.Value))).ToArray())); + new XAttribute("Id", Id), + new XElement("ComputerName", ComputerName), + new XElement("Price", Price.ToString()), + new XElement("ComputerComponents", Components.Select(x => new XElement("ComputerComponent", + new XElement("Key", x.Key), + new XElement("Value", x.Value))).ToArray())); } } diff --git a/ComputersShop/ComputersShopFileImplement/Models/Implementer.cs b/ComputersShop/ComputersShopFileImplement/Models/Implementer.cs index 8ae5a5c..5bcff0c 100644 --- a/ComputersShop/ComputersShopFileImplement/Models/Implementer.cs +++ b/ComputersShop/ComputersShopFileImplement/Models/Implementer.cs @@ -4,18 +4,25 @@ using ComputersShopDataModels.Models; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; namespace ComputersShopFileImplement.Models { + [DataContract] public class Implementer : IImplementerModel { + [DataMember] public int Id { get; set; } + [DataMember] public string ImplementerFIO { get; set; } = string.Empty; + [DataMember] public string Password { get; set; } = string.Empty; + [DataMember] public int WorkExperience { get; set; } + [DataMember] public int Qualification { get; set; } public static Implementer? Create(ImplementerBindingModel? model) { diff --git a/ComputersShop/ComputersShopFileImplement/Models/MessageInfo.cs b/ComputersShop/ComputersShopFileImplement/Models/MessageInfo.cs index 8bd1a73..6053b4c 100644 --- a/ComputersShop/ComputersShopFileImplement/Models/MessageInfo.cs +++ b/ComputersShop/ComputersShopFileImplement/Models/MessageInfo.cs @@ -4,26 +4,29 @@ using ComputersShopDataModels.Models; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; namespace ComputersShopFileImplement.Models { - public class MessageInfo : IMessageInfoModel + [DataContract] + public class MessageInfo : IMessageInfoModel { + public int Id { get; private set; } + [DataMember] public string MessageId { get; private set; } = string.Empty; - + [DataMember] public int? ClientId { get; private set; } - + [DataMember] public string SenderName { get; private set; } = string.Empty; - + [DataMember] public DateTime DateDelivery { get; private set; } = DateTime.Now; - + [DataMember] public string Subject { get; private set; } = string.Empty; - + [DataMember] public string Body { get; private set; } = string.Empty; - public static MessageInfo? Create(MessageInfoBindingModel model) { if (model == null) @@ -40,7 +43,6 @@ namespace ComputersShopFileImplement.Models Body = model.Body }; } - public static MessageInfo? Create(XElement element) { if (element == null) @@ -57,7 +59,6 @@ namespace ComputersShopFileImplement.Models Body = element.Element("Body")!.Value }; } - public MessageInfoViewModel GetViewModel => new() { MessageId = MessageId, @@ -67,7 +68,6 @@ namespace ComputersShopFileImplement.Models Subject = Subject, Body = Body }; - public XElement GetXElement => new("MessageInfo", new XAttribute("MessageId", MessageId), new XElement("ClientId", ClientId), diff --git a/ComputersShop/ComputersShopFileImplement/Models/Order.cs b/ComputersShop/ComputersShopFileImplement/Models/Order.cs index bc9e5b0..467d08d 100644 --- a/ComputersShop/ComputersShopFileImplement/Models/Order.cs +++ b/ComputersShop/ComputersShopFileImplement/Models/Order.cs @@ -8,19 +8,30 @@ using ComputersShopContracts.ViewModels; using ComputersShopDataModels.Enums; using ComputersShopDataModels.Models; using System.Xml.Linq; +using System.Runtime.Serialization; namespace ComputersShopFileImplement.Models { + [DataContract] public class Order : IOrderModel { + [DataMember] public int Id { get; private set; } + [DataMember] public int ComputerId { get; private set; } + [DataMember] public int ClientId { get; private set; } + [DataMember] public int? ImplementerId { get; private set; } + [DataMember] public int Count { get; private set; } + [DataMember] public double Sum { get; private set; } + [DataMember] public OrderStatus Status { get; private set; } + [DataMember] public DateTime DateCreate { get; private set; } + [DataMember] public DateTime? DateImplement { get; private set; } public static Order? Create(OrderBindingModel? model) { diff --git a/ComputersShop/ComputersShopListImplement/ComputersShopListImplement.csproj b/ComputersShop/ComputersShopListImplement/ComputersShopListImplement.csproj index 31f657b..15b5926 100644 --- a/ComputersShop/ComputersShopListImplement/ComputersShopListImplement.csproj +++ b/ComputersShop/ComputersShopListImplement/ComputersShopListImplement.csproj @@ -20,4 +20,8 @@ + + + + diff --git a/ComputersShop/ComputersShopListImplement/Implements/BackUpInfo.cs b/ComputersShop/ComputersShopListImplement/Implements/BackUpInfo.cs new file mode 100644 index 0000000..43935c2 --- /dev/null +++ b/ComputersShop/ComputersShopListImplement/Implements/BackUpInfo.cs @@ -0,0 +1,21 @@ +using ComputersShopContracts.StoragesContracts; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ComputersShopListImplement.Implements +{ + public class BackUpInfo : IBackUpInfo + { + public List? GetList() where T : class, new() + { + throw new NotImplementedException(); + } + public Type? GetTypeByModelInterface(string modelInterfaceName) + { + throw new NotImplementedException(); + } + } +} diff --git a/ComputersShop/ComputersShopListImplement/ListImplementationExtension.cs b/ComputersShop/ComputersShopListImplement/ListImplementationExtension.cs new file mode 100644 index 0000000..e31eb38 --- /dev/null +++ b/ComputersShop/ComputersShopListImplement/ListImplementationExtension.cs @@ -0,0 +1,27 @@ +using ComputersShopContracts.DI; +using ComputersShopContracts.StoragesContracts; +using ComputersShopListImplement.Implements; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ComputersShopListImplement +{ + public class ListImplementationExtension : IImplementationExtension + { + public int Priority => 0; + + public void RegisterServices() + { + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + } + } +} diff --git a/ComputersShop/ComputersShopListImplement/Models/MessageInfo.cs b/ComputersShop/ComputersShopListImplement/Models/MessageInfo.cs index b5e97e7..4471687 100644 --- a/ComputersShop/ComputersShopListImplement/Models/MessageInfo.cs +++ b/ComputersShop/ComputersShopListImplement/Models/MessageInfo.cs @@ -11,6 +11,7 @@ namespace ComputersShopListImplement.Models { public class MessageInfo : IMessageInfoModel { + public int Id => throw new NotImplementedException(); public string MessageId { get; private set; } = string.Empty; public int? ClientId { get; private set; } public string SenderName { get; private set; } = string.Empty; diff --git a/ComputersShop/ComputersShopView/DataGridViewExtension.cs b/ComputersShop/ComputersShopView/DataGridViewExtension.cs new file mode 100644 index 0000000..7662f2e --- /dev/null +++ b/ComputersShop/ComputersShopView/DataGridViewExtension.cs @@ -0,0 +1,46 @@ +using ComputersShopContracts.Attributes; + +namespace ComputersShopView +{ + public static class DataGridViewExtension + { + public static void FillAndConfigGrid(this DataGridView grid, List? data) + { + if (data == null) + { + return; + } + grid.DataSource = data; + + var type = typeof(T); + var properties = type.GetProperties(); + foreach (DataGridViewColumn column in grid.Columns) + { + var property = properties.FirstOrDefault(x => x.Name == column.Name); + if (property == null) + { + throw new InvalidOperationException($"В типе {type.Name} не найдено свойство с именем {column.Name}"); + } + var attribute = property.GetCustomAttributes(typeof(ColumnAttribute), true)?.SingleOrDefault(); + if (attribute == null) + { + throw new InvalidOperationException($"Не найден атрибут типа ColumnAttribute для свойства {property.Name}"); + } + // ищем нужный нам атрибут + if (attribute is ColumnAttribute columnAttr) + { + column.HeaderText = columnAttr.Title; + column.Visible = columnAttr.Visible; + if (columnAttr.IsUseAutoSize) + { + column.AutoSizeMode = (DataGridViewAutoSizeColumnMode)Enum.Parse(typeof(DataGridViewAutoSizeColumnMode), columnAttr.GridViewAutoSize.ToString()); + } + else + { + column.Width = columnAttr.Width; + } + } + } + } + } +} diff --git a/ComputersShop/ComputersShopView/FormClients.cs b/ComputersShop/ComputersShopView/FormClients.cs index 1d6e510..046ba27 100644 --- a/ComputersShop/ComputersShopView/FormClients.cs +++ b/ComputersShop/ComputersShopView/FormClients.cs @@ -17,31 +17,28 @@ namespace ComputersShopView public partial class FormClients : Form { private readonly ILogger _logger; - private readonly IClientLogic _clientLogic; - public FormClients(ILogger logger, IClientLogic clientLogic) + private readonly IClientLogic _logic; + public FormClients(ILogger logger, IClientLogic logic) { InitializeComponent(); _logger = logger; - _clientLogic = clientLogic; + _logic = logic; + LoadData(); + } + private void FormClients_Load(object sender, EventArgs e) + { LoadData(); } private void LoadData() { try { - var list = _clientLogic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["Id"].Visible = false; - dataGridView.Columns["ClientFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - dataGridView.Columns["Password"].Visible = false; - } - _logger.LogInformation("Load clients"); + dataGridView.FillAndConfigGrid(_logic.ReadList(null)); + _logger.LogInformation("Clients loading"); } catch (Exception ex) { - _logger.LogError(ex, "Load clients error"); + _logger.LogError(ex, "Clients loading error"); MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } } @@ -53,16 +50,13 @@ namespace ComputersShopView { if (dataGridView.SelectedRows.Count == 1) { - if (MessageBox.Show("Удалить запись?", "Вопрос", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + if (MessageBox.Show("Удалить клиента?", "Вопрос", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); - _logger.LogInformation("Delete client"); + _logger.LogInformation("Deletion of client"); try { - if (!_clientLogic.Delete(new ClientBindingModel - { - Id = id - })) + if (!_logic.Delete(new ClientBindingModel { Id = id })) { throw new Exception("Ошибка при удалении. Дополнительная информация в логах."); } @@ -70,7 +64,7 @@ namespace ComputersShopView } catch (Exception ex) { - _logger.LogError(ex, "Delete client error"); + _logger.LogError(ex, "Client deletion error"); MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } } diff --git a/ComputersShop/ComputersShopView/FormComponents.cs b/ComputersShop/ComputersShopView/FormComponents.cs index 5dd3e12..99daf46 100644 --- a/ComputersShop/ComputersShopView/FormComponents.cs +++ b/ComputersShop/ComputersShopView/FormComponents.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using System.Windows.Forms; using ComputersShopContracts.BindingModels; using ComputersShopContracts.BusinessLogicsContracts; +using ComputersShopContracts.DI; using Microsoft.Extensions.Logging; @@ -18,8 +19,7 @@ namespace ComputersShopView { private readonly ILogger _logger; private readonly IComponentLogic _logic; - public FormComponents(ILogger logger, IComponentLogic -logic) + public FormComponents(ILogger logger, IComponentLogic logic) { InitializeComponent(); _logger = logger; @@ -33,49 +33,32 @@ logic) { try { - var list = _logic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["Id"].Visible = false; - dataGridView.Columns["ComponentName"].AutoSizeMode = - DataGridViewAutoSizeColumnMode.Fill; - } - _logger.LogInformation("Загрузка компонентов"); + dataGridView.FillAndConfigGrid(_logic.ReadList(null)); + _logger.LogInformation("Components loading"); } catch (Exception ex) { - _logger.LogError(ex, "Ошибка загрузки компонентов"); - MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, - MessageBoxIcon.Error); + _logger.LogError(ex, "Components loading error"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void ButtonAdd_Click(object sender, EventArgs e) { - var service = - Program.ServiceProvider?.GetService(typeof(FormComponent)); - if (service is FormComponent form) + var form = DependencyManager.Instance.Resolve(); + if (form.ShowDialog() == DialogResult.OK) { - if (form.ShowDialog() == DialogResult.OK) - { - LoadData(); - } + LoadData(); } } private void ButtonUpd_Click(object sender, EventArgs e) { if (dataGridView.SelectedRows.Count == 1) { - var service = - Program.ServiceProvider?.GetService(typeof(FormComponent)); - if (service is FormComponent form) + var form = DependencyManager.Instance.Resolve(); + form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); + if (form.ShowDialog() == DialogResult.OK) { - form.Id = - Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); - if (form.ShowDialog() == DialogResult.OK) - { - LoadData(); - } + LoadData(); } } } @@ -83,18 +66,13 @@ logic) { if (dataGridView.SelectedRows.Count == 1) { - if (MessageBox.Show("Удалить запись?", "Вопрос", - MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + if (MessageBox.Show("Удалить запись?", "Вопрос", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { - int id = - Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); - _logger.LogInformation("Удаление компонента"); + int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); + _logger.LogInformation("Deletion of component"); try { - if (!_logic.Delete(new ComponentBindingModel - { - Id = id - })) + if (!_logic.Delete(new ComponentBindingModel { Id = id })) { throw new Exception("Ошибка при удалении. Дополнительная информация в логах."); } @@ -102,9 +80,8 @@ logic) } catch (Exception ex) { - _logger.LogError(ex, "Ошибка удаления компонента"); - MessageBox.Show(ex.Message, "Ошибка", - MessageBoxButtons.OK, MessageBoxIcon.Error); + _logger.LogError(ex, "Component deletion error"); + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } diff --git a/ComputersShop/ComputersShopView/FormComputer.cs b/ComputersShop/ComputersShopView/FormComputer.cs index eec94a6..7bcd1d6 100644 --- a/ComputersShop/ComputersShopView/FormComputer.cs +++ b/ComputersShop/ComputersShopView/FormComputer.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using System.Windows.Forms; using ComputersShopContracts.BindingModels; using ComputersShopContracts.BusinessLogicsContracts; +using ComputersShopContracts.DI; using ComputersShopContracts.SearchModels; using ComputersShopDataModels.Models; using Microsoft.Extensions.Logging; @@ -83,53 +84,42 @@ namespace ComputersShopView } private void ButtonAdd_Click(object sender, EventArgs e) { - var service = - Program.ServiceProvider?.GetService(typeof(FormComputerComponent)); - if (service is FormComputerComponent form) + var form = DependencyManager.Instance.Resolve(); + if (form.ShowDialog() == DialogResult.OK) { - if (form.ShowDialog() == DialogResult.OK) + if (form.ComponentModel == null) { - if (form.ComponentModel == null) - { - return; - } - _logger.LogInformation("Добавление нового компонента: { ComponentName} - { Count}", form.ComponentModel.ComponentName, form.Count); - if (_computerComponents.ContainsKey(form.Id)) - { - _computerComponents[form.Id] = (form.ComponentModel, - form.Count); - } - else - { - _computerComponents.Add(form.Id, (form.ComponentModel, - form.Count)); - } - LoadData(); + return; } + _logger.LogInformation("Adding new component: {ComponentName} - {Count}", form.ComponentModel.ComponentName, form.Count); + if (_computerComponents.ContainsKey(form.Id)) + { + _computerComponents[form.Id] = (form.ComponentModel, form.Count); + } + else + { + _computerComponents.Add(form.Id, (form.ComponentModel, form.Count)); + } + LoadData(); } } private void ButtonUpd_Click(object sender, EventArgs e) { if (dataGridView.SelectedRows.Count == 1) { - var service = - Program.ServiceProvider?.GetService(typeof(FormComputerComponent)); - if (service is FormComputerComponent form) + var form = DependencyManager.Instance.Resolve(); + int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells[0].Value); + form.Id = id; + form.Count = _computerComponents[id].Item2; + if (form.ShowDialog() == DialogResult.OK) { - int id = - Convert.ToInt32(dataGridView.SelectedRows[0].Cells[0].Value); - form.Id = id; - form.Count = _computerComponents[id].Item2; - if (form.ShowDialog() == DialogResult.OK) + if (form.ComponentModel == null) { - if (form.ComponentModel == null) - { - return; - } - _logger.LogInformation("Изменение компонента:{ ComponentName} - { Count}", form.ComponentModel.ComponentName, form.Count); - _computerComponents[form.Id] = (form.ComponentModel, form.Count); - LoadData(); + return; } + _logger.LogInformation("Component editing: {ComponentName} - {Count}", form.ComponentModel.ComponentName, form.Count); + _computerComponents[form.Id] = (form.ComponentModel, form.Count); + LoadData(); } } } diff --git a/ComputersShop/ComputersShopView/FormComputers.cs b/ComputersShop/ComputersShopView/FormComputers.cs index 835777d..ce5ec37 100644 --- a/ComputersShop/ComputersShopView/FormComputers.cs +++ b/ComputersShop/ComputersShopView/FormComputers.cs @@ -10,6 +10,7 @@ using System.Windows.Forms; using Microsoft.Extensions.Logging; using ComputersShopContracts.BindingModels; using ComputersShopContracts.BusinessLogicsContracts; +using ComputersShopContracts.DI; namespace ComputersShopView { @@ -33,32 +34,22 @@ namespace ComputersShopView { try { - var list = _logic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["Id"].Visible = false; - dataGridView.Columns["ComputerName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - dataGridView.Columns["ComputerComponents"].Visible = false; - } + dataGridView.FillAndConfigGrid(_logic.ReadList(null)); _logger.LogInformation("Computers loading"); } catch (Exception ex) { - _logger.LogError(ex, "Computers loading error"); + _logger.LogError(ex, "Ice creams loading error"); MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void ButtonAdd_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FormComputer)); - if (service is FormComputer form) + var form = DependencyManager.Instance.Resolve(); + if (form.ShowDialog() == DialogResult.OK) { - if (form.ShowDialog() == DialogResult.OK) - { - LoadData(); - } + LoadData(); } } @@ -66,14 +57,11 @@ namespace ComputersShopView { if (dataGridView.SelectedRows.Count == 1) { - var service = Program.ServiceProvider?.GetService(typeof(FormComputer)); - if (service is FormComputer form) + var form = DependencyManager.Instance.Resolve(); + form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); + if (form.ShowDialog() == DialogResult.OK) { - form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); - if (form.ShowDialog() == DialogResult.OK) - { - LoadData(); - } + LoadData(); } } } diff --git a/ComputersShop/ComputersShopView/FormImplementers.cs b/ComputersShop/ComputersShopView/FormImplementers.cs index 4ee1647..57e328a 100644 --- a/ComputersShop/ComputersShopView/FormImplementers.cs +++ b/ComputersShop/ComputersShopView/FormImplementers.cs @@ -1,5 +1,6 @@ using ComputersShopContracts.BindingModels; using ComputersShopContracts.BusinessLogicsContracts; +using ComputersShopContracts.DI; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -33,16 +34,7 @@ namespace ComputersShopView { try { - var list = _logic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["Id"].Visible = false; - dataGridView.Columns["ImplementerFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - dataGridView.Columns["Password"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - dataGridView.Columns["WorkExperience"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - dataGridView.Columns["Qualification"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - } + dataGridView.FillAndConfigGrid(_logic.ReadList(null)); _logger.LogInformation("Implementers loading"); } catch (Exception ex) @@ -54,32 +46,24 @@ namespace ComputersShopView private void ButtonAdd_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FormImplementer)); - if (service is FormImplementer form) + var form = DependencyManager.Instance.Resolve(); + if (form.ShowDialog() == DialogResult.OK) { + LoadData(); + } + } + private void ButtonEdit_Click(object sender, EventArgs e) + { + if (dataGridView.SelectedRows.Count == 1) + { + var form = DependencyManager.Instance.Resolve(); + form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); if (form.ShowDialog() == DialogResult.OK) { LoadData(); } } } - - private void ButtonEdit_Click(object sender, EventArgs e) - { - if (dataGridView.SelectedRows.Count == 1) - { - var service = Program.ServiceProvider?.GetService(typeof(FormImplementer)); - if (service is FormImplementer form) - { - form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); - if (form.ShowDialog() == DialogResult.OK) - { - LoadData(); - } - } - } - } - private void ButtonDel_Click(object sender, EventArgs e) { if (dataGridView.SelectedRows.Count == 1) diff --git a/ComputersShop/ComputersShopView/FormMails.cs b/ComputersShop/ComputersShopView/FormMails.cs index e546ce7..8e1acf3 100644 --- a/ComputersShop/ComputersShopView/FormMails.cs +++ b/ComputersShop/ComputersShopView/FormMails.cs @@ -30,14 +30,7 @@ namespace ComputersShopView { try { - var list = _logic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["MessageId"].Visible = false; - dataGridView.Columns["ClientId"].Visible = false; - dataGridView.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - } + dataGridView.FillAndConfigGrid(_logic.ReadList(null)); _logger.LogInformation("Messages loading"); } catch (Exception ex) diff --git a/ComputersShop/ComputersShopView/FormMain.Designer.cs b/ComputersShop/ComputersShopView/FormMain.Designer.cs index 2001a0a..8caa0dc 100644 --- a/ComputersShop/ComputersShopView/FormMain.Designer.cs +++ b/ComputersShop/ComputersShopView/FormMain.Designer.cs @@ -39,11 +39,12 @@ this.компонентыПоИзделиямToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.списокЗаказовToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.запускРаботToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.почтаToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.dataGridView = new System.Windows.Forms.DataGridView(); this.buttonCreateOrder = new System.Windows.Forms.Button(); this.buttonIssuedOrder = new System.Windows.Forms.Button(); this.buttonRef = new System.Windows.Forms.Button(); - this.почтаToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.создатьБэкапToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.menuStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit(); this.SuspendLayout(); @@ -55,7 +56,8 @@ this.справочникиToolStripMenuItem, this.отчетыToolStripMenuItem, this.запускРаботToolStripMenuItem, - this.почтаToolStripMenuItem}); + this.почтаToolStripMenuItem, + this.создатьБэкапToolStripMenuItem}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; this.menuStrip1.Size = new System.Drawing.Size(1147, 28); @@ -139,6 +141,13 @@ this.запускРаботToolStripMenuItem.Text = "Запуск работ"; this.запускРаботToolStripMenuItem.Click += new System.EventHandler(this.ЗапускРаботToolStripMenuItem_Click); // + // почтаToolStripMenuItem + // + this.почтаToolStripMenuItem.Name = "почтаToolStripMenuItem"; + this.почтаToolStripMenuItem.Size = new System.Drawing.Size(65, 24); + this.почтаToolStripMenuItem.Text = "Почта"; + this.почтаToolStripMenuItem.Click += new System.EventHandler(this.ПочтаToolStripMenuItem_Click); + // // dataGridView // this.dataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) @@ -183,12 +192,12 @@ this.buttonRef.UseVisualStyleBackColor = true; this.buttonRef.Click += new System.EventHandler(this.ButtonRef_Click); // - // почтаToolStripMenuItem + // создатьБэкапToolStripMenuItem // - this.почтаToolStripMenuItem.Name = "почтаToolStripMenuItem"; - this.почтаToolStripMenuItem.Size = new System.Drawing.Size(65, 24); - this.почтаToolStripMenuItem.Text = "Почта"; - this.почтаToolStripMenuItem.Click += new System.EventHandler(this.ПочтаToolStripMenuItem_Click); + this.создатьБэкапToolStripMenuItem.Name = "создатьБэкапToolStripMenuItem"; + this.создатьБэкапToolStripMenuItem.Size = new System.Drawing.Size(122, 24); + this.создатьБэкапToolStripMenuItem.Text = "Создать бэкап"; + this.создатьБэкапToolStripMenuItem.Click += new System.EventHandler(this.СоздатьБэкапToolStripMenuItem_Click); // // FormMain // @@ -230,5 +239,6 @@ private ToolStripMenuItem запускРаботToolStripMenuItem; private ToolStripMenuItem исполнителиToolStripMenuItem; private ToolStripMenuItem почтаToolStripMenuItem; + private ToolStripMenuItem создатьБэкапToolStripMenuItem; } } \ No newline at end of file diff --git a/ComputersShop/ComputersShopView/FormMain.cs b/ComputersShop/ComputersShopView/FormMain.cs index f72a866..0522709 100644 --- a/ComputersShop/ComputersShopView/FormMain.cs +++ b/ComputersShop/ComputersShopView/FormMain.cs @@ -10,6 +10,7 @@ using System.Windows.Forms; using ComputersShopBusinessLogic.BusinessLogics; using ComputersShopContracts.BindingModels; using ComputersShopContracts.BusinessLogicsContracts; +using ComputersShopContracts.DI; using Microsoft.Extensions.Logging; namespace ComputersShopView @@ -20,7 +21,8 @@ namespace ComputersShopView private readonly IOrderLogic _orderLogic; private readonly IReportLogic _reportLogic; private readonly IWorkProcess _workProcess; - public FormMain(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic, IWorkProcess workProcess) + private readonly IBackUpLogic _backUpLogic; + public FormMain(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic, IWorkProcess workProcess, IBackUpLogic backUpLogic) { InitializeComponent(); _logger = logger; @@ -28,6 +30,7 @@ namespace ComputersShopView _reportLogic = reportLogic; _reportLogic = reportLogic; _workProcess = workProcess; + _backUpLogic = backUpLogic; } private void FormMain_Load(object sender, EventArgs e) { @@ -37,52 +40,31 @@ namespace ComputersShopView { try { - var list = _orderLogic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["ComputerId"].Visible = false; - dataGridView.Columns["ComputerName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - dataGridView.Columns["ClientId"].Visible = false; - dataGridView.Columns["ClientEmail"].Visible = false; - dataGridView.Columns["ClientFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - dataGridView.Columns["ImplementerId"].Visible = false; - dataGridView.Columns["ImplementerFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - } - _logger.LogInformation("Загрузка заказов"); + dataGridView.FillAndConfigGrid(_orderLogic.ReadList(null)); + _logger.LogInformation("Orders loading"); } catch (Exception ex) { - _logger.LogError(ex, "Ошибка загрузки заказов"); + _logger.LogError(ex, "Orders loading error"); MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void КомпонентыToolStripMenuItem_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FormComponents)); - if (service is FormComponents form) - { - form.ShowDialog(); - } + var form = DependencyManager.Instance.Resolve(); + form.ShowDialog(); } private void ИзделияToolStripMenuItem_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FormComputers)); - if (service is FormComputers form) - { - form.ShowDialog(); - } + var form = DependencyManager.Instance.Resolve(); + form.ShowDialog(); } private void ButtonCreateOrder_Click(object sender, EventArgs e) { - var service = - Program.ServiceProvider?.GetService(typeof(FormCreateOrder)); - if (service is FormCreateOrder form) - { - form.ShowDialog(); - LoadData(); - } + var form = DependencyManager.Instance.Resolve(); + form.ShowDialog(); + LoadData(); } private void ButtonIssuedOrder_Click(object sender, EventArgs e) { @@ -131,51 +113,59 @@ namespace ComputersShopView private void компонентыПоКомпьютерамToolStripMenuItem_Click(object sender, EventArgs e) { - var service = - Program.ServiceProvider?.GetService(typeof(FormReportComputerComponents)); - if (service is FormReportComputerComponents form) - { - form.ShowDialog(); - } + var form = DependencyManager.Instance.Resolve(); + form.ShowDialog(); } private void списокЗаказовToolStripMenuItem_Click(object sender, EventArgs e) { - var service = - Program.ServiceProvider?.GetService(typeof(FormReportOrders)); - if (service is FormReportOrders form) + using var dialog = new SaveFileDialog { Filter = "docx|*.docx" }; + if (dialog.ShowDialog() == DialogResult.OK) { - form.ShowDialog(); + _reportLogic.SaveComputersToWordFile(new ReportBindingModel { FileName = dialog.FileName }); + MessageBox.Show("Выполнено", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information); } } private void клиентыToolStripMenuItem_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FormClients)); - if (service is FormClients form) - { - form.ShowDialog(); - } + var form = DependencyManager.Instance.Resolve(); + form.ShowDialog(); } private void ЗапускРаботToolStripMenuItem_Click(object sender, EventArgs e) { - _workProcess.DoWork((Program.ServiceProvider?.GetService(typeof(IImplementerLogic - )) as IImplementerLogic)!, _orderLogic); - MessageBox.Show("Процесс обработки запущен", "Сообщение", - MessageBoxButtons.OK, MessageBoxIcon.Information); + _workProcess.DoWork(DependencyManager.Instance.Resolve(), _orderLogic); + MessageBox.Show("Процесс обработки запущен", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information); } private void ИсполнителиToolStripMenuItem_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FormImplementers)); - if (service is FormImplementers form) - { - form.ShowDialog(); - } + var form = DependencyManager.Instance.Resolve(); + form.ShowDialog(); } private void ПочтаToolStripMenuItem_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FormMails)); - if (service is FormMails form) + var form = DependencyManager.Instance.Resolve(); + form.ShowDialog(); + } + private void СоздатьБэкапToolStripMenuItem_Click(object sender, EventArgs e) + { + try { - form.ShowDialog(); + if (_backUpLogic != null) + { + var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() == DialogResult.OK) + { + _backUpLogic.CreateBackUp(new BackUpSaveBindingModel + { + FolderName = fbd.SelectedPath + }); + MessageBox.Show("Бэкап создан", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка создания бэкапа", MessageBoxButtons.OK, + MessageBoxIcon.Error); } } } diff --git a/ComputersShop/ComputersShopView/Program.cs b/ComputersShop/ComputersShopView/Program.cs index 2c90e09..34e90ec 100644 --- a/ComputersShop/ComputersShopView/Program.cs +++ b/ComputersShop/ComputersShopView/Program.cs @@ -2,21 +2,17 @@ using ComputersShopBusinessLogic.BusinessLogics; using ComputersShopBusinessLogic.OfficePackage.Implements; using ComputersShopBusinessLogic.OfficePackage; using ComputersShopContracts.BusinessLogicsContracts; -using ComputersShopContracts.StoragesContracts; -using ComputersShopDatabaseImplement.Implements; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; -using System; using ComputersShopBusinessLogic.MailWorker; using ComputersShopContracts.BindingModels; +using ComputersShopContracts.DI; +using ComputersShopView; -namespace ComputersShopView +namespace ComputerShopView { internal static class Program { - private static ServiceProvider? _serviceProvider; - public static ServiceProvider? ServiceProvider => _serviceProvider; /// /// The main entry point for the application. /// @@ -26,12 +22,10 @@ namespace ComputersShopView // To customize application configuration such as set high DPI settings or default font, // see https://aka.ms/applicationconfiguration. ApplicationConfiguration.Initialize(); - var services = new ServiceCollection(); - ConfigureServices(services); - _serviceProvider = services.BuildServiceProvider(); + InitDependency(); try { - var mailSender = _serviceProvider.GetService(); + var mailSender = DependencyManager.Instance.Resolve(); mailSender?.MailConfig(new MailConfigBindingModel { MailLogin = System.Configuration.ConfigurationManager.AppSettings["MailLogin"] ?? string.Empty, @@ -46,56 +40,52 @@ namespace ComputersShopView } catch (Exception ex) { - var logger = _serviceProvider.GetService(); + var logger = DependencyManager.Instance.Resolve(); logger?.LogError(ex, "Mails Problem"); } - Application.Run(_serviceProvider.GetRequiredService()); + Application.Run(DependencyManager.Instance.Resolve()); } - private static void ConfigureServices(ServiceCollection services) + + private static void InitDependency() { - services.AddLogging(option => + DependencyManager.InitDependency(); + + DependencyManager.Instance.AddLogging(option => { option.SetMinimumLevel(LogLevel.Information); option.AddNLog("nlog.config"); }); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); - services.AddTransient(); - services.AddSingleton(); - - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(true); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); } - private static void MailCheck(object obj) => ServiceProvider?.GetService()?.MailCheck(); + private static void MailCheck(object obj) => DependencyManager.Instance.Resolve()?.MailCheck(); } } \ No newline at end of file diff --git a/ComputersShop/ImplementationExtensions/ComputersShopContracts.dll b/ComputersShop/ImplementationExtensions/ComputersShopContracts.dll new file mode 100644 index 0000000000000000000000000000000000000000..b15538ed6e3ac8328bb2db7f116cd07e420a3b00 GIT binary patch literal 31744 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 literal 0 HcmV?d00001 diff --git a/ComputersShop/ImplementationExtensions/ComputersShopListImplement.dll b/ComputersShop/ImplementationExtensions/ComputersShopListImplement.dll new file mode 100644 index 0000000000000000000000000000000000000000..700a55403e813d44e587b1f6e90813996ba9d45e GIT binary patch literal 26624 zcmeHwdw5&bmG3%7($T}VY{|~sBue6dh#l7<0g@2Fj-7`~oCkISE(wWjD~XEi<4QJ= zLO>w_8Xj$-Kw*HA6w;QKbO_K=piGkwI+Qzo1TN((y|fbs3T5W@qqIY3(yuq%-&%X0 zqa)i1wDZrM@4KQ}TCctK+H3E%&N@eO+VQC`l8=b|cz^gI(f9DluV#TK2L*_u)1Hpf z6XBms|DLh(C)2yOW%7x^oV_)d>QD5h1_tb*L{B=A8y-kx1`=(nI}`nOU%IiPB2uSK zuUSg8((utmZHs>E%yyJ!B+85?qRrq~io5Jud?xTN;7wE|xT*YR2Kz6sLxAA(%SW59 zXI1`R@l%t`!t0OM5UpmUKy-uyG4i#Ss2sds>>%nIDLWaRAPRZpA(l2-!U##}zv3rc(|0O5u9;O%)eW4ju2>8uS!_LcVH&9=7S?Rhm5E%A_o zp2l&-i+wXGKttG%z6C^vaQ}KR!%RkrA~d^4Bj$u#7sK4F@xJ?Zz^H%rd5*w0iiXer z*^%+HF>Q5|N$Z{Ila(+z-p25H(l}II9NXsN2#<>gJUEV#%MUU>8=l6*)2ZfFu;2&7 zw?hyxU`8CAoXv5V54%`zjC{(jkLph|ePSaiHbAhAq}Tw#HaJce z&HiqFJcwClG6K?`036dNaY`(Eq9(9kmOY7y*im4#5dc?}Irvc|sAUu|x&;&wa+0&Vry-F{d*Wy_;!l;%c2-b)V zPz*u9Kx`F55HPSSiXjMmcFqc-TpEYP`P1P5;xGd)u!pkrnM}YbA?la_M~GQW0DSaW zVH-)Yftaw3q}Tw#Hj-jv_P^#&1%a3#PL_@6N`Md>%T8(nj#)OG6bbBDHj)+5`mBx? z2f@tOgSUfM>j@lAnTmoS2n)`qVh92Tsq}W8b#P8+!i11PodBnVNvQWuL`_ z8~;i~NN)v4(TV?L4oKv)2q6lO3ZWoiAQ==x5HOH_iXjLX$PmR41PtVsVh92T(nc`^ zk@aoC+E6b_&-eN~md*RJ0N&V(SOdgDCUA`q0?dego+i#=qFEErh}cUsaV`^WOz2JG zoa*9$;+4mEjwuXVHVTeJ4z?_|B?N|BHnvmq9h0yD7A_q2pA}TiXjLXC}oNv2pA}5iXjLXNL9rU z1PoLS#SjFHgu@U743q(-Aqe8dvAY$Y!IAs5Bfk+5z!ojTBJFnIykFSEh<$-3Rxr__ z31~#@)tdMu6KgdA^@!c6iIq&O(*(vw?29z9iivI}yt#+NKQj0D`p0IHVg>|{Ov*?Q z>_<}k!1dEdS7AKA@?i0~fX|k_1~}&$+_czDAz;$7FVqA~TI{n(pl;bXU_wB{;spo+ zre&|!1U@ZZjYuwL0szOS*ldtaMg8dtF4QN5%;c9bZU-u@A4OpbuK$>hd&wB(vA{@# z%&S;vf05093Y@a~32`HN39xdqLfmLr_6DAoz{U>DT(CQYKca|yLW&37F>!^Qc0_9hHTZU!g|qN%aU>(irrsHmS8_lXbHev0|+ayX#| z+9?dI4#WZtRb)ZpagQ)W{Cgh$`AYpOucwgf-yCZ0FZy?u!An3qJf1Zqe0GoHW<#}) zd*MhK*58NE@yCsNV>~*t5Y?0~IL7N78N-SNhrul_!DD*PnI-EsW&D_RLeNr9Mtk(&u{{| zXx@h(emE+oH6=0apjW0Fde41yKUQBRF`Zy<#Z;psR94^Qo-&_wvmtTuxQXyqgd4CO ziZS70ZNWW$FN`{Vz9i0_6|vCJR{LZA28(K{1NF6@U9s$K?1m*vgN$MU90z?~r_i|< z7taGi#P>b1(LP7&8{;IWvW$W{pa>NLSsrSLQ_yE)kOdLPuj1F!2- z27x%W1E=xh)(#vhXFi|(8Q2(AJ4$^}wS#?7wF6gE9DE))vUYgfDuA-ujHJU z){a-OS2%iHJ6zAWT;wp@*yZ9Oj2IQRiuxSp*DiZZNhv7$FSTM0lG|%ulDkIM=&(%8`O{1JIw&GYNL_N-wTlaoEIKaJ{9xYRj{w%6`VA$ z>q_z(>qeekiBX)_EVDn4_1fFPQF)EZr1Cn+eDpyoudfE;wUFN*jE_+N# zUKjm$^V(}(@)~V8*66TLp4Yr;o!7Ero!6cfpFFQ8$a*K(*J6#FBc)4Gd96->Po5}* zZ1%1subF|oRu(v~#Sxv?9!Gr1Q=vJ=_1c}&vJ32nJSzAYd5wD`$!mAKoLZIF>@(-J ziY0noPhOt}Hz4BB>AV(?bzXZs{)oJu#PjRCc73qyotUg-UY*w?RFKym4*F%zYw@X= z*RF!Si&t>cyq;B(*OS?|{BDfmyk?nwJJxGo501*~8-U66`Yh((2uiNkp9A9Lb@b!s zHEN|ZpU>U{8_CT8-d?}d2bI_CgUag$IH3lP%xjN(oY&%?&TFrKC&}v&di`4V&*K^Q z`Zqala+2T7?&{XKwAcS9!fRv}%(wLer z@Lm_B5X=@GhrI=AC+^-kOuBpL5G_i%-Mc4B-dfN>U;AU}HU1Qd(FFSzj32#XRSVRq z@yS!M5I?vptp&_LEl?J?7RYw#THtZSmz)pHF=~N(N-X_;QTo80Ez*$zcU>Wlv#QtOR?gZl0 z0z~(tukk+m0kUFxaXz1Y7n_co&OJ2NA3~@X+ylK)&Q$yBx5WKP_NF?3n>G6!xZ@0N znCCE*(drk%C?7}-H4ErIu#X#jhg)sMEO}@U;0I97+6c4A;%-A5>_0w!^x{+> zd^Y93>Ewt>LvR^a60Re7yrL?c^A*j;QHv?BuZKgtmI^%}%#SH8`);u0hBZQAajJ~_ za#K0o1%IE3$iC^%dBa~dt!RJ>;q#@?B zzv^Y^Bew7#5Vz58R)-eg!cOs!ay3k`FhAzAs>?>$o#Pu{AB~k^mIq-y`4CSv$D>>_ z=LqHfP-ZtGu}Fg~Gd#vJL$b_8IdxSCmFx^Hcn()cpZzr$a>8C+9xHFSdW;ou7~#)6@#pJaf2v|t3sFtS3UaLe;&@EC6sK66 zpW|BPKAVSE*WehjQ}LP+MWV(j64lkQYUN~n3@2mC$p>&eVk4YnZ+!MQc$V?;@yUl7 z85bMZuzifEO{iZHpP*cvNU@3h6xgbs9G|Sl-!dL)a(w*hcr;~ylg&(uO;RpR9K)pv z%B8=DOA|_6vZ|-x8P}BAaLj0i7t}zV*Qz`-=@q&&qn_27^fjaNn1e4g(_b;=8JAIj5>=R@x+tKGnJ!(}MTSFxY zTmGx*?xApIZrG~h&*{nWZ&;5U=j}&+$@Yh|ZDe4{6rlArqG2Y6$aaL|;jy>Fxr~hR z2p4Lc06mei*w8k@r8)DoOVuGKY|5A7s?|u)p34>|GrsupmMq=fak*M_@VN7A)>E-m zcSqDx%X?4MiuZa1?H;^kQ$h2-qQuZ?vab{DZ^7E={ZhRim)CMEa2Y;BHka6v`#xr% z*HaeU!moQhk6XUvr=U5q*PG!f>6ZNnyJ5;#4(f8^Jk?Rxi_&Mc8Tg-M|3{s(Nd0^~ zePzG7-(v@r_wuZEB0sCW1Uxc>#kA60pIiiOKF59F-$ zeH*;KSoQ(9P%=L*WAjI=pzp&*sLQKme_Mj!xu$xa+`4M^-$P5^3Er&S<2`*Az98>o zd2|Qs42NRFr`P&&>euRf(3nP~O1RJZ5aOQ6WI_LZ9D(m-j1)^VV zp>A35Uq74grWN~Cobg>FLae@P6a)8ZHj7Enci2AM2 zTFlQcw>ipx2Tmt%#!AS{f0uFGlQ8}y<6ltt_ZYuT;ZHG+mXCFwW*ki>en118{EUAl zKH*`EuEFW`tKZ?2Qyv|%RbYc5=<59XJGTV!SS)`ttdW zO^x%K=FMFQ0>5U+0zQu$x|!DyHBH6uv8sS~4&^cfTl1`O2d^8SGuL&}-M}HHnakI; zx8d^}puZmmy(G)uhsg`|#JFg}SHs~b$UhtN2$w9B75PmA@`Z4M2#y;%g^-WuBL7{0KR0>oT>rg+ z>9jPk|07_G#zDuRL%xRr*ZUp=yv6qn;MaZ60}l9p0=U@sYQUoFBmW#&li<^G!^HQH zNd|Sh)W1S2=Th&1y3VCocDqn-huf-ZRX_l7V9IQh?wc4Yy-o#+wjhR}PJyFq1zVqbz*gubU_@Fi-M(Z6ZUwUHXDoF?&QM*C7ubA(d9 zl+&3)DPPLzJT3b}z{Ypa%e2e~Un*#|mi^XWK&`w;%l_cs4QjKN-5UJ@F4Ehy?4jsa z5bYtM*w0B;jD9Q>$1GvRsk}}+L(ERKs%g2Rw>5OF zmfeooYUp!X#``ypzNlrqf8*#LEt?j&4412YT6PA`+<5w?mLhNd+@x&VDS(9i;QCPzwYcjo{C|Sc~dRr*9hRO6hP5mBTPo@uq+8H_yuP4)S zEn8*0KvT%VO%~D4&?UyJpeluWJNycErIsdW*_(kXPzf!YQgwt*A^tvv$2C+P1vOX8 zeiyY-PZw(0v1k>jC0Z7)vS}K9Qp@61RiL_r;?*`=3Hp&xH(-4$tQnL<+v%L88MI9( zwZ0iND3scx8MIx?nvBcP=j_z7^9=*kODR0P|Mzo><0ByEqf;VM^x}vwd^0Gej`c$tYum2 z2zvK-wCpPDD5&3S+3A(Xa1HuTEjy>O3>}vr4H^+gX%%|ay+ZMsSZ_7ZQAHtU8?8CC z6>X{$vpF;<)Z50dD|;ckQd39#16CsyJep0kr-a(8HD9hAwwkDlTRwW*c)apjP>*VA zYUM4~T=JvGW!WQ@cUbf2kfzes9oCuD%xxEB`#_yd|0tBIQVZ#IEql50UTYz(M9;^X z&sFXR^}jVWwem4*5xvgMoy_pGwV3X1QdHV{+B%OW&Q;VtP|freq0|gZ=m{-*x$>~J zgzETlrOfb8pq|&%)XHC2t@Ok^C3~dusI`;^=PN309krIz?=`g#R6AXMCdd0Gt3WOM2`ujtaQ_lwCv@|bA#Qq zc(G$;1*lifSJc$X^}$ckBQ1`VO~DP6U81P8wJCTh{kx|2f!a)kR+jCgo6EKZduT%& zQ#XX{=x2hx)TgOyqE~_H*VHW)Hw61=SW{oF_#&ulH1&MNy}>lypsAND_JjI@rshT; z4Q`Z=t$3~r@wXzKBbpMg54sTJkF3~r;RG_|h$El|%3wNol)hU%8G z*LP7k@Ln)OokFRYWoUy?yHKnD9Ww4iFA0qeuSd6Ppa=Qur969a)XD95XaD$`JW9Pz z?4j54iSXi#jy?V~=y1SUyLXn4gDZbNj;2@V|D93)6;Dolmb~%*MOlEB;tr`D?+)Ch zrtt1SpVp6e2YRxdcz59Lf;9i?K?;3ycPX}CM zod%DXbC9@0K1kdPA0+O24-)rBPl@y?;;#59;{Nw3;!f#(%#{0%##V%uy z#BC3}eF0DSSA{MG|J}(J_D@AjI*m>CCv+=Old0*^wiL^`X zbcr2YTVbb9>}18xkl5)H%^|V#l$?{NWW7&`wXnoFD>_-RmKAGRv39js+bz~^5o=eA z<}G6FML8`m%E@`(xUqbfv0J2f$f)~d)I&1r4&gr}qh6DFUo(ChIYy62v|lp{WsGyQ zPd9E1eaC;gaX;W|V*fQcGq2&C{J{T&=6R1NZE&_O)*fY?nhSV=@H+up=@METZbda)9A1ig^;RGyoD?#)Bit)^uSk2TmwLi! z(b*~douac#@Li&_3p#tk*Ne_R;qMcj{lYmcoWsI-4o`BHho2Mv4+Xv<(lsnDbiU2n?>59A?vh?POC_l3fwHxl!mO6 z7JflEJ2hnfUcvVnlWBc;pT?R0pxAs+MjaCVVGUXOoJgM&>5DSh~{+BoGzL(MRTS|X9;W(X^Ti(McOL- zr20ZJ2X~@z;f*;n9IY$M5Lqq0}Pu8U&a}t72 z*N{2QK8`?(a9VuK*({uta8knADfmvo_X)mF@I!(h){w^@75ohinL~c@K||*F{c+5g z5YBWBncpnA3P?tl%vgGH0{kDGixZ5PYYG z%-JjWJ`I`kP+&4W8a^bP!x}RGd71I3aNYp^7XJQ*XHN*M!;_hoaI@f>1@;N2fcyWJ z@Lqur3Fj?=i6D<{7T6Z#v6}@i2;424y@DSS_`GnA3Qi#&>kml`1#cF(Szw>=3xYo+ z_*()gEZz#N3yZgcZx&b(xLf#p1wSP4dEp!toFX!BMCKK|Szw!RHVa-5xL4pq!apSV zQGss>hswkgfz4$cpSCiIfZzqd<>B4JIVAY=f*%#!kM9i-=NMbqEU+MOufRhBj|!x? z%p$N^;AVjZfqMm}DUZJy*+b9JVfr0SFnWy78Q(IVHGXWoZbZ%5X0v&riEK6RH=i

GPNSVtI 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 literal 0 HcmV?d00001