From 22c6e6abbbb134c715470845c60846b292fced54 Mon Sep 17 00:00:00 2001 From: eegov Date: Sun, 26 Feb 2023 15:52:16 +0400 Subject: [PATCH] reflections --- .../BusinessLogics/BackUpLogic.cs | 98 ++++++++++++++++++ .../AbstractShopContracts.csproj | 4 + .../Attributes/ColumnAttribute.cs | 25 +++++ .../Attributes/GridViewAutoSize.cs | 21 ++++ .../BindingModels/BackUpSaveBinidngModel.cs | 7 ++ .../BindingModels/MessageInfoBindingModel.cs | 2 + .../BusinessLogicsContracts/IBackUpLogic.cs | 9 ++ .../DI/DependencyManager.cs | 61 +++++++++++ .../DI/IDependencyContainer.cs | 35 +++++++ .../DI/IImplementationExtension.cs | 11 ++ .../DI/ServiceDependencyContainer.cs | 57 ++++++++++ .../DI/ServiceProviderLoader.cs | 50 +++++++++ .../StoragesContracts/IBackUpInfo.cs | 9 ++ .../ViewModels/ClientViewModel.cs | 11 +- .../ViewModels/MessageInfoViewModel.cs | 2 + .../Models/IMessageInfoModel.cs | 2 +- .../Implements/BackUpInfo.cs | 27 +++++ .../AbstractShopListImplement.csproj | 4 + .../Implements/BackUpInfo.cs | 17 +++ .../ListImplementationExtension.cs | 22 ++++ .../AbstractShopView/DataGridViewExtension.cs | 46 ++++++++ AbstractShop/AbstractShopView/FormClients.cs | 8 +- .../AbstractShopView/FormComponents.cs | 12 +-- AbstractShop/AbstractShopView/Program.cs | 73 ++++++------- .../AbstractShopContracts.dll | Bin 0 -> 29184 bytes .../AbstractShopDataModels.dll | Bin 0 -> 6144 bytes .../AbstractShopListImplement.dll | Bin 0 -> 13312 bytes 27 files changed, 551 insertions(+), 62 deletions(-) create mode 100644 AbstractShop/AbstractShopBusinessLogic/BusinessLogics/BackUpLogic.cs create mode 100644 AbstractShop/AbstractShopContracts/Attributes/ColumnAttribute.cs create mode 100644 AbstractShop/AbstractShopContracts/Attributes/GridViewAutoSize.cs create mode 100644 AbstractShop/AbstractShopContracts/BindingModels/BackUpSaveBinidngModel.cs create mode 100644 AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IBackUpLogic.cs create mode 100644 AbstractShop/AbstractShopContracts/DI/DependencyManager.cs create mode 100644 AbstractShop/AbstractShopContracts/DI/IDependencyContainer.cs create mode 100644 AbstractShop/AbstractShopContracts/DI/IImplementationExtension.cs create mode 100644 AbstractShop/AbstractShopContracts/DI/ServiceDependencyContainer.cs create mode 100644 AbstractShop/AbstractShopContracts/DI/ServiceProviderLoader.cs create mode 100644 AbstractShop/AbstractShopContracts/StoragesContracts/IBackUpInfo.cs create mode 100644 AbstractShop/AbstractShopDatabaseImplement/Implements/BackUpInfo.cs create mode 100644 AbstractShop/AbstractShopListImplement/Implements/BackUpInfo.cs create mode 100644 AbstractShop/AbstractShopListImplement/ListImplementationExtension.cs create mode 100644 AbstractShop/AbstractShopView/DataGridViewExtension.cs create mode 100644 AbstractShop/ImplementationExtensions/AbstractShopContracts.dll create mode 100644 AbstractShop/ImplementationExtensions/AbstractShopDataModels.dll create mode 100644 AbstractShop/ImplementationExtensions/AbstractShopListImplement.dll diff --git a/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/BackUpLogic.cs b/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/BackUpLogic.cs new file mode 100644 index 0000000..9653f44 --- /dev/null +++ b/AbstractShop/AbstractShopBusinessLogic/BusinessLogics/BackUpLogic.cs @@ -0,0 +1,98 @@ +using AbstractShopContracts.BindingModels; +using AbstractShopContracts.BusinessLogicsContracts; +using AbstractShopContracts.StoragesContracts; +using AbstractShopDataModels; +using Microsoft.Extensions.Logging; +using System.IO.Compression; +using System.Reflection; +using System.Runtime.Serialization.Json; + +namespace AbstractShopBusinessLogic.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(BackUpSaveBinidngModel 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); + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/AbstractShopContracts.csproj b/AbstractShop/AbstractShopContracts/AbstractShopContracts.csproj index e652bca..9a4e1c1 100644 --- a/AbstractShop/AbstractShopContracts/AbstractShopContracts.csproj +++ b/AbstractShop/AbstractShopContracts/AbstractShopContracts.csproj @@ -6,6 +6,10 @@ enable + + + + diff --git a/AbstractShop/AbstractShopContracts/Attributes/ColumnAttribute.cs b/AbstractShop/AbstractShopContracts/Attributes/ColumnAttribute.cs new file mode 100644 index 0000000..ee2962f --- /dev/null +++ b/AbstractShop/AbstractShopContracts/Attributes/ColumnAttribute.cs @@ -0,0 +1,25 @@ +namespace AbstractShopContracts.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; + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/Attributes/GridViewAutoSize.cs b/AbstractShop/AbstractShopContracts/Attributes/GridViewAutoSize.cs new file mode 100644 index 0000000..83bd453 --- /dev/null +++ b/AbstractShop/AbstractShopContracts/Attributes/GridViewAutoSize.cs @@ -0,0 +1,21 @@ +namespace AbstractShopContracts.Attributes +{ + public enum GridViewAutoSize + { + NotSet = 0, + + None = 1, + + ColumnHeader = 2, + + AllCellsExceptHeader = 4, + + AllCells = 6, + + DisplayedCellsExceptHeader = 8, + + DisplayedCells = 10, + + Fill = 16 + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/BindingModels/BackUpSaveBinidngModel.cs b/AbstractShop/AbstractShopContracts/BindingModels/BackUpSaveBinidngModel.cs new file mode 100644 index 0000000..9fe504f --- /dev/null +++ b/AbstractShop/AbstractShopContracts/BindingModels/BackUpSaveBinidngModel.cs @@ -0,0 +1,7 @@ +namespace AbstractShopContracts.BindingModels +{ + public class BackUpSaveBinidngModel + { + public string FolderName { get; set; } = string.Empty; + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/BindingModels/MessageInfoBindingModel.cs b/AbstractShop/AbstractShopContracts/BindingModels/MessageInfoBindingModel.cs index 16397de..568c037 100644 --- a/AbstractShop/AbstractShopContracts/BindingModels/MessageInfoBindingModel.cs +++ b/AbstractShop/AbstractShopContracts/BindingModels/MessageInfoBindingModel.cs @@ -15,5 +15,7 @@ namespace AbstractShopContracts.BindingModels public string Body { get; set; } = string.Empty; public DateTime DateDelivery { get; set; } + + public int Id => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IBackUpLogic.cs b/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IBackUpLogic.cs new file mode 100644 index 0000000..8f36e95 --- /dev/null +++ b/AbstractShop/AbstractShopContracts/BusinessLogicsContracts/IBackUpLogic.cs @@ -0,0 +1,9 @@ +using AbstractShopContracts.BindingModels; + +namespace AbstractShopContracts.BusinessLogicsContracts +{ + public interface IBackUpLogic + { + void CreateBackUp(BackUpSaveBinidngModel model); + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/DI/DependencyManager.cs b/AbstractShop/AbstractShopContracts/DI/DependencyManager.cs new file mode 100644 index 0000000..33366e6 --- /dev/null +++ b/AbstractShop/AbstractShopContracts/DI/DependencyManager.cs @@ -0,0 +1,61 @@ +using Microsoft.Extensions.Logging; + +namespace AbstractShopContracts.DI +{ + public class DependencyManager + { + private readonly IDependencyContainer _dependencyManager; + + private static DependencyManager? _manager; + + private static readonly object _locjObject = new(); + + private DependencyManager() + { + _dependencyManager = new ServiceDependencyContainer(); + } + + public static DependencyManager Instance { get { if (_manager == null) { lock (_locjObject) { _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(); + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/DI/IDependencyContainer.cs b/AbstractShop/AbstractShopContracts/DI/IDependencyContainer.cs new file mode 100644 index 0000000..c6f4acc --- /dev/null +++ b/AbstractShop/AbstractShopContracts/DI/IDependencyContainer.cs @@ -0,0 +1,35 @@ +using Microsoft.Extensions.Logging; + +namespace AbstractShopContracts.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(); + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/DI/IImplementationExtension.cs b/AbstractShop/AbstractShopContracts/DI/IImplementationExtension.cs new file mode 100644 index 0000000..8a40af2 --- /dev/null +++ b/AbstractShop/AbstractShopContracts/DI/IImplementationExtension.cs @@ -0,0 +1,11 @@ +namespace AbstractShopContracts.DI +{ + public interface IImplementationExtension + { + public int Priority { get; } + /// + /// Регистрация сервисов + /// + public void RegisterServices(); + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/DI/ServiceDependencyContainer.cs b/AbstractShop/AbstractShopContracts/DI/ServiceDependencyContainer.cs new file mode 100644 index 0000000..f7817fd --- /dev/null +++ b/AbstractShop/AbstractShopContracts/DI/ServiceDependencyContainer.cs @@ -0,0 +1,57 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace AbstractShopContracts.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()!; + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/DI/ServiceProviderLoader.cs b/AbstractShop/AbstractShopContracts/DI/ServiceProviderLoader.cs new file mode 100644 index 0000000..7600ca7 --- /dev/null +++ b/AbstractShop/AbstractShopContracts/DI/ServiceProviderLoader.cs @@ -0,0 +1,50 @@ +using System.Reflection; + +namespace AbstractShopContracts.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"; + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/StoragesContracts/IBackUpInfo.cs b/AbstractShop/AbstractShopContracts/StoragesContracts/IBackUpInfo.cs new file mode 100644 index 0000000..712c644 --- /dev/null +++ b/AbstractShop/AbstractShopContracts/StoragesContracts/IBackUpInfo.cs @@ -0,0 +1,9 @@ +namespace AbstractShopContracts.StoragesContracts +{ + public interface IBackUpInfo + { + List? GetList() where T : class, new(); + + Type? GetTypeByModelInterface(string modelInterfaceName); + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/ViewModels/ClientViewModel.cs b/AbstractShop/AbstractShopContracts/ViewModels/ClientViewModel.cs index 9843f5d..e2507e8 100644 --- a/AbstractShop/AbstractShopContracts/ViewModels/ClientViewModel.cs +++ b/AbstractShop/AbstractShopContracts/ViewModels/ClientViewModel.cs @@ -1,19 +1,20 @@ -using AbstractShopDataModels.Models; -using System.ComponentModel; +using AbstractShopContracts.Attributes; +using AbstractShopDataModels.Models; namespace AbstractShopContracts.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; } } \ No newline at end of file diff --git a/AbstractShop/AbstractShopContracts/ViewModels/MessageInfoViewModel.cs b/AbstractShop/AbstractShopContracts/ViewModels/MessageInfoViewModel.cs index d84d6d5..f3419e2 100644 --- a/AbstractShop/AbstractShopContracts/ViewModels/MessageInfoViewModel.cs +++ b/AbstractShop/AbstractShopContracts/ViewModels/MessageInfoViewModel.cs @@ -20,5 +20,7 @@ namespace AbstractShopContracts.ViewModels [DisplayName("Текст")] public string Body { get; set; } = string.Empty; + + public int Id => throw new NotImplementedException(); } } \ No newline at end of file diff --git a/AbstractShop/AbstractShopDataModels/Models/IMessageInfoModel.cs b/AbstractShop/AbstractShopDataModels/Models/IMessageInfoModel.cs index e51db32..d8a1dc9 100644 --- a/AbstractShop/AbstractShopDataModels/Models/IMessageInfoModel.cs +++ b/AbstractShop/AbstractShopDataModels/Models/IMessageInfoModel.cs @@ -1,6 +1,6 @@ namespace AbstractShopDataModels.Models { - public interface IMessageInfoModel + public interface IMessageInfoModel : IId { string MessageId { get; } diff --git a/AbstractShop/AbstractShopDatabaseImplement/Implements/BackUpInfo.cs b/AbstractShop/AbstractShopDatabaseImplement/Implements/BackUpInfo.cs new file mode 100644 index 0000000..afca497 --- /dev/null +++ b/AbstractShop/AbstractShopDatabaseImplement/Implements/BackUpInfo.cs @@ -0,0 +1,27 @@ +using AbstractShopContracts.StoragesContracts; + +namespace AbstractShopDatabaseImplement.Implements +{ + public class BackUpInfo : IBackUpInfo + { + public List? GetList() where T : class, new() + { + using var context = new AbstractShopDatabase(); + 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; + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopListImplement/AbstractShopListImplement.csproj b/AbstractShop/AbstractShopListImplement/AbstractShopListImplement.csproj index 81fc427..ba40e9e 100644 --- a/AbstractShop/AbstractShopListImplement/AbstractShopListImplement.csproj +++ b/AbstractShop/AbstractShopListImplement/AbstractShopListImplement.csproj @@ -11,4 +11,8 @@ + + + + diff --git a/AbstractShop/AbstractShopListImplement/Implements/BackUpInfo.cs b/AbstractShop/AbstractShopListImplement/Implements/BackUpInfo.cs new file mode 100644 index 0000000..bf948d2 --- /dev/null +++ b/AbstractShop/AbstractShopListImplement/Implements/BackUpInfo.cs @@ -0,0 +1,17 @@ +using AbstractShopContracts.StoragesContracts; + +namespace AbstractShopListImplement.Implements +{ + public class BackUpInfo : IBackUpInfo + { + public List? GetList() where T : class, new() + { + throw new NotImplementedException(); + } + + public Type? GetTypeByModelInterface(string modelInterfaceName) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopListImplement/ListImplementationExtension.cs b/AbstractShop/AbstractShopListImplement/ListImplementationExtension.cs new file mode 100644 index 0000000..0dde1e9 --- /dev/null +++ b/AbstractShop/AbstractShopListImplement/ListImplementationExtension.cs @@ -0,0 +1,22 @@ +using AbstractShopContracts.DI; +using AbstractShopContracts.StoragesContracts; +using AbstractShopListImplement.Implements; + +namespace AbstractShopListImplement +{ + 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(); + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopView/DataGridViewExtension.cs b/AbstractShop/AbstractShopView/DataGridViewExtension.cs new file mode 100644 index 0000000..98ec60e --- /dev/null +++ b/AbstractShop/AbstractShopView/DataGridViewExtension.cs @@ -0,0 +1,46 @@ +using AbstractShopContracts.Attributes; + +namespace AbstractShopView +{ + internal 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; + } + } + } + } + } +} \ No newline at end of file diff --git a/AbstractShop/AbstractShopView/FormClients.cs b/AbstractShop/AbstractShopView/FormClients.cs index 72e0c97..438a6ef 100644 --- a/AbstractShop/AbstractShopView/FormClients.cs +++ b/AbstractShop/AbstractShopView/FormClients.cs @@ -26,13 +26,7 @@ namespace AbstractShopView { try { - var list = _logic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["Id"].Visible = false; - dataGridView.Columns["ClientFIO"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - } + dataGridView.FillAndConfigGrid(_logic.ReadList(null)); _logger.LogInformation("Загрузка клиентов"); } catch (Exception ex) diff --git a/AbstractShop/AbstractShopView/FormComponents.cs b/AbstractShop/AbstractShopView/FormComponents.cs index 883aa37..0788486 100644 --- a/AbstractShop/AbstractShopView/FormComponents.cs +++ b/AbstractShop/AbstractShopView/FormComponents.cs @@ -1,5 +1,6 @@ using AbstractShopContracts.BindingModels; using AbstractShopContracts.BusinessLogicsContracts; +using AbstractShopContracts.DI; using Microsoft.Extensions.Logging; namespace AbstractShopView @@ -44,13 +45,10 @@ namespace AbstractShopView 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(); } } @@ -58,7 +56,7 @@ namespace AbstractShopView { if (dataGridView.SelectedRows.Count == 1) { - var service = Program.ServiceProvider?.GetService(typeof(FormComponent)); + var service = DependencyManager.Instance.Resolve(); if (service is FormComponent form) { form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value); diff --git a/AbstractShop/AbstractShopView/Program.cs b/AbstractShop/AbstractShopView/Program.cs index b662e57..347d51b 100644 --- a/AbstractShop/AbstractShopView/Program.cs +++ b/AbstractShop/AbstractShopView/Program.cs @@ -4,9 +4,7 @@ using AbstractShopBusinessLogic.OfficePackage; using AbstractShopBusinessLogic.OfficePackage.Implements; using AbstractShopContracts.BindingModels; using AbstractShopContracts.BusinessLogicsContracts; -using AbstractShopContracts.StoragesContracts; -using AbstractShopDatabaseImplement.Implements; -using Microsoft.Extensions.DependencyInjection; +using AbstractShopContracts.DI; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; @@ -14,9 +12,6 @@ namespace AbstractShopView { internal static class Program { - private static ServiceProvider? _serviceProvider; - public static ServiceProvider? ServiceProvider => _serviceProvider; - /// /// The main entry point for the application. /// @@ -26,13 +21,11 @@ namespace AbstractShopView // 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, @@ -48,53 +41,49 @@ namespace AbstractShopView } catch (Exception ex) { - var logger = _serviceProvider.GetService(); + var logger = DependencyManager.Instance.Resolve(); logger?.LogError(ex, " "); } // Application.Run(new Form1()); } - 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(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(true); + DependencyManager.Instance.RegisterType(); - 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(); + 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/AbstractShop/ImplementationExtensions/AbstractShopContracts.dll b/AbstractShop/ImplementationExtensions/AbstractShopContracts.dll new file mode 100644 index 0000000000000000000000000000000000000000..9c010c2f5331eb2af7e57cc1bd01a6cab0cef45f GIT binary patch literal 29184 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 Vp1-lZSlw`+b9euD|G$-i{{WmuQr!Rm literal 0 HcmV?d00001 diff --git a/AbstractShop/ImplementationExtensions/AbstractShopListImplement.dll b/AbstractShop/ImplementationExtensions/AbstractShopListImplement.dll new file mode 100644 index 0000000000000000000000000000000000000000..9382f70dd2accd7e271701edbe843efef7e5f69e GIT binary patch literal 13312 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