From 9e2af7b3d07a28d380bb0e8a49da342263d796a9 Mon Sep 17 00:00:00 2001 From: kirinzx Date: Tue, 14 May 2024 11:56:24 +0400 Subject: [PATCH] all done --- .../FurnitureAssembly/App.config | 4 +- .../FurnitureAssembly/ClientsForm.cs | 15 +-- .../FurnitureAssembly/ComponentsForm.cs | 30 ++--- .../DataGridViewExtension.cs | 51 +++++++++ .../FurnitureAssembly/FormMail.cs | 9 +- .../FurnitureAssemblyView.csproj | 19 ++-- .../FurnitureAssembly/FurnitureForm.cs | 44 ++++---- .../FurnitureAssembly/FurnituresForm.cs | 32 ++---- .../FurnitureAssembly/ImplementersForm.cs | 35 ++---- .../FurnitureAssembly/MainForm.Designer.cs | 12 +- .../FurnitureAssembly/MainForm.cs | 104 +++++++++--------- .../FurnitureAssembly/Program.cs | 90 ++++++++------- .../BusinessLogics/BackUpLogic.cs | 97 ++++++++++++++++ .../BusinessLogics/MessageInfoLogic.cs | 50 +-------- .../MailWorker/AbstractMailWorker.cs | 1 + .../Attributes/ColumnAttribute.cs | 24 ++++ .../Attributes/GridViewAutoSize.cs | 14 +++ .../BindingModels/BackUpSaveBinidngModel.cs | 7 ++ .../BindingModels/MessageInfoBindingModel.cs | 1 + .../BusinessLogicsContracts/IBackUpLogic.cs | 9 ++ .../DI/DependencyManager.cs | 64 +++++++++++ .../DI/IDependencyContainer.cs | 34 ++++++ .../DI/IImplementationExtension.cs | 11 ++ .../DI/ServiceDependencyContainer.cs | 57 ++++++++++ .../DI/ServiceProviderLoader.cs | 52 +++++++++ .../DI/UnityDependencyContainer.cs | 52 +++++++++ .../FurnitureAssemblyContracts.csproj | 7 +- .../StoragesContracts/IBackUpInfo.cs | 8 ++ .../ViewModels/ClientViewModel.cs | 10 +- .../ViewModels/ComponentViewModel.cs | 8 +- .../ViewModels/FurnitureViewModel.cs | 9 +- .../ViewModels/ImplementerViewModel.cs | 13 ++- .../ViewModels/MessageInfoViewModel.cs | 16 ++- .../ViewModels/OrderViewModel.cs | 39 ++++--- .../FurnitureAssemblyDataModels.csproj | 4 - .../Models/IMessageInfoModel.cs | 2 +- .../DatabaseImplementationExtension.cs | 22 ++++ .../FurnitureAssemblyDatabase.cs | 58 +++++----- .../FurnitureAssemblyDatabaseImplement.csproj | 51 +++++---- .../Implements/BackUpInfo.cs | 26 +++++ .../Implements/MessageInfoStorage.cs | 9 +- .../Models/Client.cs | 6 + .../Models/Component.cs | 5 + .../Models/Furniture.cs | 6 + .../Models/FurnitureComponent.cs | 1 - .../Models/Implementer.cs | 7 ++ .../Models/MessageInfo.cs | 14 ++- .../Models/Order.cs | 14 ++- .../FileImplementationExtension.cs | 22 ++++ .../FurnitureAssemblyFileImplement.csproj | 8 +- .../Implements/BackUpInfo.cs | 31 ++++++ .../Models/Client.cs | 9 +- .../Models/Component.cs | 5 + .../Models/Furniture.cs | 6 + .../Models/Implementer.cs | 10 +- .../Models/MessageInfo.cs | 14 ++- .../Models/Order.cs | 19 ++-- .../FurnitureAssemblyListImplement.csproj | 8 +- .../Implements/BackUpInfo.cs | 18 +++ .../ListImplementationExtension.cs | 22 ++++ .../Models/MessageInfo.cs | 1 + .../FurnitureAssemblyContracts.dll | Bin 0 -> 32256 bytes .../FurnitureAssemblyDataModels.dll | Bin 0 -> 7168 bytes .../FurnitureAssemblyFileImplement.dll | Bin 0 -> 41472 bytes .../FurnitureAssemblyListImplement.dll | Bin 0 -> 26112 bytes 65 files changed, 1019 insertions(+), 407 deletions(-) create mode 100644 FurnitureAssembly/FurnitureAssembly/DataGridViewExtension.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/BackUpLogic.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/Attributes/ColumnAttribute.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/Attributes/GridViewAutoSize.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/BackUpSaveBinidngModel.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/BusinessLogicsContracts/IBackUpLogic.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/DI/DependencyManager.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/DI/IDependencyContainer.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/DI/IImplementationExtension.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/DI/ServiceDependencyContainer.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/DI/ServiceProviderLoader.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/DI/UnityDependencyContainer.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyContracts/StoragesContracts/IBackUpInfo.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyDatabaseImplement/DatabaseImplementationExtension.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/BackUpInfo.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyFileImplement/FileImplementationExtension.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyFileImplement/Implements/BackUpInfo.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyListImplement/Implements/BackUpInfo.cs create mode 100644 FurnitureAssembly/FurnitureAssemblyListImplement/ListImplementationExtension.cs create mode 100644 FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyContracts.dll create mode 100644 FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyDataModels.dll create mode 100644 FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyFileImplement.dll create mode 100644 FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyListImplement.dll diff --git a/FurnitureAssembly/FurnitureAssembly/App.config b/FurnitureAssembly/FurnitureAssembly/App.config index 37f0651..e835b00 100644 --- a/FurnitureAssembly/FurnitureAssembly/App.config +++ b/FurnitureAssembly/FurnitureAssembly/App.config @@ -5,7 +5,7 @@ - - + + \ No newline at end of file diff --git a/FurnitureAssembly/FurnitureAssembly/ClientsForm.cs b/FurnitureAssembly/FurnitureAssembly/ClientsForm.cs index af45a86..e5e98af 100644 --- a/FurnitureAssembly/FurnitureAssembly/ClientsForm.cs +++ b/FurnitureAssembly/FurnitureAssembly/ClientsForm.cs @@ -1,4 +1,5 @@ -using FurnitureAssemblyContracts.BindingModels; +using FurnitureAssembly; +using FurnitureAssemblyContracts.BindingModels; using FurnitureAssemblyContracts.BusinessLogicsContracts; using Microsoft.Extensions.Logging; using System; @@ -32,17 +33,7 @@ namespace FurnitureAssemblyView { try { - var list = _logic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["Id"].Visible = false; - dataGridView.Columns["ClientFIO"].AutoSizeMode = - DataGridViewAutoSizeColumnMode.Fill; - dataGridView.Columns["Email"].AutoSizeMode = - DataGridViewAutoSizeColumnMode.Fill; - dataGridView.Columns["Password"].Visible = false; - } + dataGridView.FillandConfigGrid(_logic.ReadList(null)); _logger.LogInformation("Загрузка клиентов"); } catch (Exception ex) diff --git a/FurnitureAssembly/FurnitureAssembly/ComponentsForm.cs b/FurnitureAssembly/FurnitureAssembly/ComponentsForm.cs index 3d1ab9a..346d203 100644 --- a/FurnitureAssembly/FurnitureAssembly/ComponentsForm.cs +++ b/FurnitureAssembly/FurnitureAssembly/ComponentsForm.cs @@ -1,6 +1,7 @@ using FurnitureAssembly; using FurnitureAssemblyContracts.BindingModels; using FurnitureAssemblyContracts.BusinessLogicsContracts; +using FurnitureAssemblyContracts.DI; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -33,13 +34,7 @@ namespace FurnitureAssemblyView { try { - var list = _logic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["Id"].Visible = false; - dataGridView.Columns["ComponentName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - } + dataGridView.FillandConfigGrid(_logic.ReadList(null)); _logger.LogInformation("Загрузка компонентов"); } catch (Exception ex) @@ -52,13 +47,10 @@ namespace FurnitureAssemblyView private void buttonAdd_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(ComponentForm)); - if (service is ComponentForm form) + var form = DependencyManager.Instance.Resolve(); + if (form.ShowDialog() == DialogResult.OK) { - if (form.ShowDialog() == DialogResult.OK) - { - LoadData(); - } + LoadData(); } } @@ -102,15 +94,11 @@ namespace FurnitureAssemblyView { if (dataGridView.SelectedRows.Count == 1) { - var service = - Program.ServiceProvider?.GetService(typeof(ComponentForm)); - if (service is ComponentForm 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/FurnitureAssembly/FurnitureAssembly/DataGridViewExtension.cs b/FurnitureAssembly/FurnitureAssembly/DataGridViewExtension.cs new file mode 100644 index 0000000..6952f2e --- /dev/null +++ b/FurnitureAssembly/FurnitureAssembly/DataGridViewExtension.cs @@ -0,0 +1,51 @@ +using FurnitureAssemblyContracts.Attributes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FurnitureAssembly +{ + 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/FurnitureAssembly/FurnitureAssembly/FormMail.cs b/FurnitureAssembly/FurnitureAssembly/FormMail.cs index fd2afdb..5fe7996 100644 --- a/FurnitureAssembly/FurnitureAssembly/FormMail.cs +++ b/FurnitureAssembly/FurnitureAssembly/FormMail.cs @@ -20,14 +20,7 @@ namespace FurnitureAssembly { try { - var list = _logic.ReadList(null); - if (list != null) - { - dataGridViewMail.DataSource = list; - dataGridViewMail.Columns["ClientId"].Visible = false; - dataGridViewMail.Columns["MessageId"].Visible = false; - dataGridViewMail.Columns["Body"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - } + dataGridViewMail.FillandConfigGrid(_logic.ReadList(null)); _logger.LogInformation("Загрузка писем"); } catch (Exception ex) diff --git a/FurnitureAssembly/FurnitureAssembly/FurnitureAssemblyView.csproj b/FurnitureAssembly/FurnitureAssembly/FurnitureAssemblyView.csproj index 98ebae3..17b56b1 100644 --- a/FurnitureAssembly/FurnitureAssembly/FurnitureAssemblyView.csproj +++ b/FurnitureAssembly/FurnitureAssembly/FurnitureAssemblyView.csproj @@ -8,17 +8,14 @@ enable - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/FurnitureAssembly/FurnitureAssembly/FurnitureForm.cs b/FurnitureAssembly/FurnitureAssembly/FurnitureForm.cs index db12f3c..d7108b3 100644 --- a/FurnitureAssembly/FurnitureAssembly/FurnitureForm.cs +++ b/FurnitureAssembly/FurnitureAssembly/FurnitureForm.cs @@ -13,6 +13,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; +using FurnitureAssemblyContracts.DI; namespace FurnitureAssemblyView { @@ -85,35 +86,34 @@ namespace FurnitureAssemblyView private void buttonAdd_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FurnitureComponentForm)); - if (service is FurnitureComponentForm form) - { - if (form.ShowDialog() == DialogResult.OK) - { - if (form.ComponentModel == null) - { - return; - } - _logger.LogInformation("Добавление нового компонента:{ ComponentName} - { Count}", form.ComponentModel.ComponentName, form.Count); - if (_furnitureComponents.ContainsKey(form.Id)) - { - _furnitureComponents[form.Id] = (form.ComponentModel, form.Count); - } - else - { - _furnitureComponents.Add(form.Id, (form.ComponentModel, form.Count)); - } - LoadData(); - } - } + var form = DependencyManager.Instance.Resolve(); + if (form.ShowDialog() == DialogResult.OK) + { + if (form.ComponentModel == null) + { + return; + } + _logger.LogInformation("Добавление нового компонента: { ComponentName}- { Count}", form.ComponentModel.ComponentName, form.Count); + if (_furnitureComponents.ContainsKey(form.Id)) + { + _furnitureComponents[form.Id] = (form.ComponentModel, + form.Count); + } + else + { + _furnitureComponents.Add(form.Id, (form.ComponentModel, + form.Count)); + } + LoadData(); + } } private void buttonChange_Click(object sender, EventArgs e) { if (dataGridView.SelectedRows.Count == 1) { - var service = Program.ServiceProvider?.GetService(typeof(FurnitureComponentForm)); + var service = DependencyManager.Instance.Resolve(); if (service is FurnitureComponentForm form) { int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells[0].Value); diff --git a/FurnitureAssembly/FurnitureAssembly/FurnituresForm.cs b/FurnitureAssembly/FurnitureAssembly/FurnituresForm.cs index e141d16..ceb9353 100644 --- a/FurnitureAssembly/FurnitureAssembly/FurnituresForm.cs +++ b/FurnitureAssembly/FurnitureAssembly/FurnituresForm.cs @@ -10,6 +10,7 @@ using System.Windows.Forms; using FurnitureAssembly; using FurnitureAssemblyContracts.BindingModels; using FurnitureAssemblyContracts.BusinessLogicsContracts; +using FurnitureAssemblyContracts.DI; using FurnitureAssemblyView; using Microsoft.Extensions.Logging; @@ -31,15 +32,7 @@ namespace FurnitureAssemblyView { try { - var list = _logic.ReadList(null); - - if (list != null) - { - DataGridView.DataSource = list; - DataGridView.Columns["Id"].Visible = false; - DataGridView.Columns["FurnitureComponents"].Visible = false; - DataGridView.Columns["FurnitureName"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; - } + DataGridView.FillandConfigGrid(_logic.ReadList(null)); _logger.LogInformation("Загрузка компонентов"); @@ -53,30 +46,23 @@ namespace FurnitureAssemblyView private void AddButton_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FurnitureForm)); + var form = DependencyManager.Instance.Resolve(); - if (service is FurnitureForm form) + if (form.ShowDialog() == DialogResult.OK) { - if (form.ShowDialog() == DialogResult.OK) - { - LoadData(); - } + LoadData(); } } private void ChangeButton_Click(object sender, EventArgs e) { if (DataGridView.SelectedRows.Count == 1) { - var service = Program.ServiceProvider?.GetService(typeof(FurnitureForm)); + var form = DependencyManager.Instance.Resolve(); - if (service is FurnitureForm form) + 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/FurnitureAssembly/FurnitureAssembly/ImplementersForm.cs b/FurnitureAssembly/FurnitureAssembly/ImplementersForm.cs index 81af3be..89251fb 100644 --- a/FurnitureAssembly/FurnitureAssembly/ImplementersForm.cs +++ b/FurnitureAssembly/FurnitureAssembly/ImplementersForm.cs @@ -1,6 +1,7 @@ using FurnitureAssembly; using FurnitureAssemblyContracts.BindingModels; using FurnitureAssemblyContracts.BusinessLogicsContracts; +using FurnitureAssemblyContracts.DI; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -33,15 +34,7 @@ namespace FurnitureAssemblyView { try { - var list = _logic.ReadList(null); - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["Id"].Visible = false; - dataGridView.Columns["ImplementerFIO"].AutoSizeMode = - DataGridViewAutoSizeColumnMode.Fill; - } - _logger.LogInformation("Загрузка исполнителей"); + dataGridView.FillandConfigGrid(_logic.ReadList(null)); } catch (Exception ex) { @@ -53,13 +46,11 @@ namespace FurnitureAssemblyView private void ButtonAdd_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(ImplementerForm)); - if (service is ImplementerForm form) + var form = DependencyManager.Instance.Resolve(); + + if (form.ShowDialog() == DialogResult.OK) { - if (form.ShowDialog() == DialogResult.OK) - { - LoadData(); - } + LoadData(); } } @@ -67,16 +58,12 @@ namespace FurnitureAssemblyView { if (dataGridView.SelectedRows.Count == 1) { - var service = - Program.ServiceProvider?.GetService(typeof(ImplementerForm)); - if (service is ImplementerForm 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/FurnitureAssembly/FurnitureAssembly/MainForm.Designer.cs b/FurnitureAssembly/FurnitureAssembly/MainForm.Designer.cs index 7029b7e..01ef100 100644 --- a/FurnitureAssembly/FurnitureAssembly/MainForm.Designer.cs +++ b/FurnitureAssembly/FurnitureAssembly/MainForm.Designer.cs @@ -46,6 +46,7 @@ this.списокЗаказовToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.запускРаботToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.mailToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.CreateBackUpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); buttonReady = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit(); this.menuStrip.SuspendLayout(); @@ -131,7 +132,8 @@ this.справочникиToolStripMenuItem, this.отчетыToolStripMenuItem, this.запускРаботToolStripMenuItem, - this.mailToolStripMenuItem}); + this.mailToolStripMenuItem, + this.CreateBackUpToolStripMenuItem}); this.menuStrip.Location = new System.Drawing.Point(0, 0); this.menuStrip.Name = "menuStrip"; this.menuStrip.Padding = new System.Windows.Forms.Padding(4, 1, 0, 1); @@ -216,6 +218,13 @@ this.запускРаботToolStripMenuItem.Text = " Запуск работ"; this.запускРаботToolStripMenuItem.Click += new System.EventHandler(this.doWorkToolStripMenuItem_Click); // + // CreateBackUpToolStripMenuItem + // + this.CreateBackUpToolStripMenuItem.Name = "CreateBackUpToolStripMenuItem"; + this.CreateBackUpToolStripMenuItem.Size = new System.Drawing.Size(97, 20); + this.CreateBackUpToolStripMenuItem.Text = "Создать Бэкап"; + this.CreateBackUpToolStripMenuItem.Click += new System.EventHandler(this.CreateBackUpToolStripMenuItem_Click); + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); @@ -260,5 +269,6 @@ private ToolStripMenuItem исполнителиToolStripMenuItem; private ToolStripMenuItem запускРаботToolStripMenuItem; private ToolStripMenuItem mailToolStripMenuItem; + private ToolStripMenuItem CreateBackUpToolStripMenuItem; } } \ No newline at end of file diff --git a/FurnitureAssembly/FurnitureAssembly/MainForm.cs b/FurnitureAssembly/FurnitureAssembly/MainForm.cs index 26f272e..b335dcc 100644 --- a/FurnitureAssembly/FurnitureAssembly/MainForm.cs +++ b/FurnitureAssembly/FurnitureAssembly/MainForm.cs @@ -12,6 +12,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; +using FurnitureAssemblyContracts.BusinessLogicsContarcts; +using FurnitureAssemblyContracts.DI; namespace FurnitureAssemblyView { @@ -21,14 +23,15 @@ namespace FurnitureAssemblyView private readonly IOrderLogic _orderLogic; private readonly IReportLogic _reportLogic; private readonly IWorkProcess _workModeling; - - public MainForm(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic, IWorkProcess workModeling) + private readonly IBackUpLogic _backUpLogic; + public MainForm(ILogger logger, IOrderLogic orderLogic, IReportLogic reportLogic, IWorkProcess workModeling, IBackUpLogic backUpLogic) { InitializeComponent(); _logger = logger; _orderLogic = orderLogic; _reportLogic = reportLogic; _workModeling = workModeling; + _backUpLogic = backUpLogic; } private void MainForm_Load(object sender, EventArgs e) @@ -40,15 +43,7 @@ namespace FurnitureAssemblyView _logger.LogInformation("Загрузка заказов"); try { - var list = _orderLogic.ReadList(null); - - if (list != null) - { - dataGridView.DataSource = list; - dataGridView.Columns["FurnitureId"].Visible = false; - dataGridView.Columns["ClientId"].Visible = false; - dataGridView.Columns["ImplementerId"].Visible = false; - } + dataGridView.FillandConfigGrid(_orderLogic.ReadList(null)); _logger.LogInformation("Загрузка заказов"); } @@ -61,31 +56,24 @@ namespace FurnitureAssemblyView private void компонентыToolStripMenuItem_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(ComponentsForm)); - if (service is ComponentsForm form) - { - form.ShowDialog(); - } + var form = DependencyManager.Instance.Resolve(); + + form.ShowDialog(); } private void изделияToolStripMenuItem_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FurnituresForm)); + var form = DependencyManager.Instance.Resolve(); - if (service is FurnituresForm form) - { - form.ShowDialog(); - } + form.ShowDialog(); } private void buttonCreate_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(OrderForm)); - if (service is OrderForm form) - { - form.ShowDialog(); - LoadData(); - } + var form = DependencyManager.Instance.Resolve(); + + form.ShowDialog(); + LoadData(); } private void buttonToWork_Click(object sender, EventArgs e) @@ -216,54 +204,64 @@ namespace FurnitureAssemblyView private void FurnituresComponentsToolStripMenuItem_Click(object sender, EventArgs e) { - var service = - Program.ServiceProvider?.GetService(typeof(ReportFurnitureComponentsForm)); - if (service is ReportFurnitureComponentsForm form) - { - form.ShowDialog(); - } + var form = DependencyManager.Instance.Resolve(); + + form.ShowDialog(); } private void OrdersToolStripMenuItem_Click(object sender, EventArgs e) { - var service = - Program.ServiceProvider?.GetService(typeof(ReportOrdersForm)); - if (service is ReportOrdersForm form) - { - form.ShowDialog(); - } + var form = DependencyManager.Instance.Resolve(); + + form.ShowDialog(); } private void ClientsToolStripMenuItem_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(ClientsForm)); - if (service is ClientsForm form) - { - form.ShowDialog(); - } + var form = DependencyManager.Instance.Resolve(); + form.ShowDialog(); } private void ImplementersToolStripMenuItem_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(ImplementersForm)); - if (service is ImplementersForm form) - { - form.ShowDialog(); - } + var form = DependencyManager.Instance.Resolve(); + + form.ShowDialog(); } private void doWorkToolStripMenuItem_Click(object sender, EventArgs e) { _workModeling.DoWork(( - Program.ServiceProvider?.GetService(typeof(IImplementerLogic)) as IImplementerLogic)!, + DependencyManager.Instance.Resolve() as IImplementerLogic)!, _orderLogic); } private void mailToolStripMenuItem_Click(object sender, EventArgs e) { - var service = Program.ServiceProvider?.GetService(typeof(FormMail)); - if (service is FormMail form) + var form = DependencyManager.Instance.Resolve(); + form.ShowDialog(); + } + private void CreateBackUpToolStripMenuItem_Click(object sender, EventArgs e) + { + try { - form.ShowDialog(); + if (_backUpLogic != null) + { + var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() == DialogResult.OK) + { + _backUpLogic.CreateBackUp(new BackUpSaveBinidngModel + { + FolderName = fbd.SelectedPath + }); + MessageBox.Show("Бекап создан", "Сообщение", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, + MessageBoxIcon.Error); } } } diff --git a/FurnitureAssembly/FurnitureAssembly/Program.cs b/FurnitureAssembly/FurnitureAssembly/Program.cs index bc8ddcc..e9a82f5 100644 --- a/FurnitureAssembly/FurnitureAssembly/Program.cs +++ b/FurnitureAssembly/FurnitureAssembly/Program.cs @@ -2,13 +2,13 @@ using FurnitureAssemblyBusinessLogic; using FurnitureAssemblyBusinessLogic.OfficePackage.Implements; using FurnitureAssemblyBusinessLogic.OfficePackage; using FurnitureAssemblyContracts.BusinessLogicsContarcts; -using FurnitureAssemblyContracts.StoragesContracts; -using FurnitureAssemblyDatabaseImplement.Implements; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; using FurnitureAssemblyBusinessLogic.MailWorker; using FurnitureAssemblyContracts.BindingModels; +using FurnitureAssemblyContracts.DI; +using FurnitureAssemblyContracts.StoragesContracts; +using FurnitureAssemblyDatabaseImplement.Implements; using FurnitureAssemblyContracts.BusinessLogicsContracts; using FurnitureAssemblyBusinessLogic.BusinessLogics; using FurnitureAssemblyView; @@ -17,8 +17,6 @@ namespace FurnitureAssembly { internal static class Program { - private static ServiceProvider? _serviceProvider; - public static ServiceProvider? ServiceProvider => _serviceProvider; /// /// The main entry point for the application. /// @@ -28,13 +26,10 @@ namespace FurnitureAssembly // 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 = @@ -57,57 +52,60 @@ namespace FurnitureAssembly } catch (Exception ex) { - var logger = _serviceProvider.GetService(); + var logger = DependencyManager.Instance.Resolve(); logger?.LogError(ex, " "); } - 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(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); - 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(); - services.AddSingleton(); + DependencyManager.Instance.RegisterType(true); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + DependencyManager.Instance.RegisterType(); + DependencyManager.Instance.RegisterType(); + 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(); - 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(); + 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/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/BackUpLogic.cs b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/BackUpLogic.cs new file mode 100644 index 0000000..ef5ed08 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/BackUpLogic.cs @@ -0,0 +1,97 @@ +using FurnitureAssemblyContracts.BindingModels; +using FurnitureAssemblyContracts.BusinessLogicsContarcts; +using FurnitureAssemblyContracts.StoragesContracts; +using FurnitureAssemblyDataModels; +using Microsoft.Extensions.Logging; +using System.IO.Compression; +using System.Reflection; +using System.Runtime.Serialization.Json; + +namespace FurnitureAssemblyBusinessLogic +{ + 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); + } + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/MessageInfoLogic.cs b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/MessageInfoLogic.cs index b800ec7..1425e6c 100644 --- a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/MessageInfoLogic.cs +++ b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/BusinessLogics/MessageInfoLogic.cs @@ -11,18 +11,15 @@ namespace FurnitureAssemblyBusinessLogic { private readonly ILogger _logger; private readonly IMessageInfoStorage _messageInfoStorage; - private readonly IClientStorage _clientStorage; - public MessageInfoLogic(ILogger logger, IMessageInfoStorage messageInfoStorage, IClientStorage clientStorage) + public MessageInfoLogic(ILogger logger, IMessageInfoStorage messageInfoStorage) { _logger = logger; _messageInfoStorage = messageInfoStorage; - _clientStorage = clientStorage; - } + } public bool Create(MessageInfoBindingModel model) - { - CheckModel(model); + { if (_messageInfoStorage.Insert(model) == null) { _logger.LogWarning("Insert operation failed"); @@ -43,46 +40,5 @@ namespace FurnitureAssemblyBusinessLogic _logger.LogInformation("ReadList. Count:{Count}", list.Count); return list; } - private void CheckModel(MessageInfoBindingModel model, bool withParams = true) - { - if (model == null) - { - throw new ArgumentNullException(nameof(model)); - } - if (!withParams) - { - return; - } - if (string.IsNullOrEmpty(model.MessageId)) - { - throw new ArgumentNullException("Не указан id сообщения", nameof(model.MessageId)); - } - if (string.IsNullOrEmpty(model.SenderName)) - { - throw new ArgumentNullException("Не указао почта", nameof(model.SenderName)); - } - if (string.IsNullOrEmpty(model.Subject)) - { - throw new ArgumentNullException("Не указана тема", nameof(model.Subject)); - } - if (string.IsNullOrEmpty(model.Body)) - { - throw new ArgumentNullException("Не указан текст сообщения", nameof(model.Subject)); - } - - _logger.LogInformation("MessageInfo. MessageId:{MessageId}.SenderName:{SenderName}.Subject:{Subject}.Body:{Body}", model.MessageId, model.SenderName, model.Subject, model.Body); - var element = _clientStorage.GetElement(new ClientSearchModel - { - Email = model.SenderName - }); - if (element == null) - { - _logger.LogWarning("Не удалоссь найти клиента, отправившего письмо с адреса Email:{Email}", model.SenderName); - } - else - { - model.ClientId = element.Id; - } - } } } diff --git a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/MailWorker/AbstractMailWorker.cs b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/MailWorker/AbstractMailWorker.cs index 49c4399..d14afed 100644 --- a/FurnitureAssembly/FurnitureAssemblyBusinessLogic/MailWorker/AbstractMailWorker.cs +++ b/FurnitureAssembly/FurnitureAssemblyBusinessLogic/MailWorker/AbstractMailWorker.cs @@ -72,6 +72,7 @@ namespace FurnitureAssemblyBusinessLogic.MailWorker _logger.LogDebug("Check Mail: {Count} new mails", list.Count); foreach (var mail in list) { + mail.ClientId = _clientLogic.ReadElement(new() { Email = mail.SenderName })?.Id; _messageInfoLogic.Create(mail); } } diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/Attributes/ColumnAttribute.cs b/FurnitureAssembly/FurnitureAssemblyContracts/Attributes/ColumnAttribute.cs new file mode 100644 index 0000000..f453606 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/Attributes/ColumnAttribute.cs @@ -0,0 +1,24 @@ +using System; + +namespace FurnitureAssemblyContracts.Attributes +{ + [AttributeUsage(AttributeTargets.Property)] + public class ColumnAttribute : Attribute + { + 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; + } + 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; } + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/Attributes/GridViewAutoSize.cs b/FurnitureAssembly/FurnitureAssemblyContracts/Attributes/GridViewAutoSize.cs new file mode 100644 index 0000000..722d1bb --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/Attributes/GridViewAutoSize.cs @@ -0,0 +1,14 @@ +namespace FurnitureAssemblyContracts.Attributes +{ + public enum GridViewAutoSize + { + NotSet = 0, + None = 1, + ColumnHeader = 2, + AllCellsExceptHeader = 4, + AllCells = 6, + DisplayedCellsExceptHeader = 8, + DisplayedCells = 10, + Fill = 16 + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/BackUpSaveBinidngModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/BackUpSaveBinidngModel.cs new file mode 100644 index 0000000..23320f7 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/BackUpSaveBinidngModel.cs @@ -0,0 +1,7 @@ +namespace FurnitureAssemblyContracts.BindingModels +{ + public class BackUpSaveBinidngModel + { + public string FolderName { get; set; } = string.Empty; + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/MessageInfoBindingModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/MessageInfoBindingModel.cs index 10e611a..ef4b265 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/MessageInfoBindingModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/BindingModels/MessageInfoBindingModel.cs @@ -15,5 +15,6 @@ namespace FurnitureAssemblyContracts.BindingModels public string Subject { get; set; } = string.Empty; public string Body { get; set; } = string.Empty; + public int Id => throw new NotImplementedException(); } } diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/BusinessLogicsContracts/IBackUpLogic.cs b/FurnitureAssembly/FurnitureAssemblyContracts/BusinessLogicsContracts/IBackUpLogic.cs new file mode 100644 index 0000000..c0f25b3 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/BusinessLogicsContracts/IBackUpLogic.cs @@ -0,0 +1,9 @@ +using FurnitureAssemblyContracts.BindingModels; + +namespace FurnitureAssemblyContracts.BusinessLogicsContarcts +{ + public interface IBackUpLogic + { + void CreateBackUp(BackUpSaveBinidngModel model); + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/DI/DependencyManager.cs b/FurnitureAssembly/FurnitureAssemblyContracts/DI/DependencyManager.cs new file mode 100644 index 0000000..6b99863 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/DI/DependencyManager.cs @@ -0,0 +1,64 @@ +using Microsoft.Extensions.Logging; + +namespace FurnitureAssemblyContracts.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(); + + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/DI/IDependencyContainer.cs b/FurnitureAssembly/FurnitureAssemblyContracts/DI/IDependencyContainer.cs new file mode 100644 index 0000000..e0fbe35 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/DI/IDependencyContainer.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.Logging; + +namespace FurnitureAssemblyContracts.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/FurnitureAssembly/FurnitureAssemblyContracts/DI/IImplementationExtension.cs b/FurnitureAssembly/FurnitureAssemblyContracts/DI/IImplementationExtension.cs new file mode 100644 index 0000000..0878428 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/DI/IImplementationExtension.cs @@ -0,0 +1,11 @@ +namespace FurnitureAssemblyContracts.DI +{ + public interface IImplementationExtension + { + public int Priority { get; } + /// + /// Регистрация сервисов + /// + public void RegisterServices(); + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/DI/ServiceDependencyContainer.cs b/FurnitureAssembly/FurnitureAssemblyContracts/DI/ServiceDependencyContainer.cs new file mode 100644 index 0000000..cebccbe --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/DI/ServiceDependencyContainer.cs @@ -0,0 +1,57 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace FurnitureAssemblyContracts.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/FurnitureAssembly/FurnitureAssemblyContracts/DI/ServiceProviderLoader.cs b/FurnitureAssembly/FurnitureAssemblyContracts/DI/ServiceProviderLoader.cs new file mode 100644 index 0000000..6778099 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/DI/ServiceProviderLoader.cs @@ -0,0 +1,52 @@ +using System.Reflection; + +namespace FurnitureAssemblyContracts.DI +{ + public static partial 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/FurnitureAssembly/FurnitureAssemblyContracts/DI/UnityDependencyContainer.cs b/FurnitureAssembly/FurnitureAssemblyContracts/DI/UnityDependencyContainer.cs new file mode 100644 index 0000000..6425937 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/DI/UnityDependencyContainer.cs @@ -0,0 +1,52 @@ +using Microsoft.Extensions.Logging; +using Unity; +using Unity.Microsoft.Logging; + +namespace FurnitureAssemblyContracts.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 T : class + { + if (isSingle) + { + container.RegisterSingleton(); + } + else + { + container.RegisterType(); + } + } + + public T Resolve() + { + return container.Resolve(); + } + + void IDependencyContainer.RegisterType(bool isSingle) + { + if (isSingle) + { + container.RegisterSingleton(); + } + else + { + container.RegisterType(); + } + } + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/FurnitureAssemblyContracts.csproj b/FurnitureAssembly/FurnitureAssemblyContracts/FurnitureAssemblyContracts.csproj index 6a503df..a8e5f90 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/FurnitureAssemblyContracts.csproj +++ b/FurnitureAssembly/FurnitureAssemblyContracts/FurnitureAssemblyContracts.csproj @@ -6,8 +6,11 @@ enable - - + + + + + diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/StoragesContracts/IBackUpInfo.cs b/FurnitureAssembly/FurnitureAssemblyContracts/StoragesContracts/IBackUpInfo.cs new file mode 100644 index 0000000..f770812 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyContracts/StoragesContracts/IBackUpInfo.cs @@ -0,0 +1,8 @@ +namespace FurnitureAssemblyContracts.StoragesContracts +{ + public interface IBackUpInfo + { + List? GetList() where T : class, new(); + Type? GetTypeByModelInterface(string modelInterfaceName); + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ClientViewModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ClientViewModel.cs index 22784d6..d4dec8a 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ClientViewModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ClientViewModel.cs @@ -1,4 +1,5 @@ -using FurnitureAssemblyDataModels.Models; +using FurnitureAssemblyContracts.Attributes; +using FurnitureAssemblyDataModels.Models; using System; using System.Collections.Generic; using System.ComponentModel; @@ -10,12 +11,13 @@ namespace FurnitureAssemblyContracts.ViewModels { public class ClientViewModel : IClientModel { + [Column(visible: false)] public int Id { get; set; } - [DisplayName("ФИО клиента")] + [Column(title: "ФИО клиента", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string ClientFIO { get; set; } = string.Empty; - [DisplayName("Логин (эл. почта)")] + [Column(title: "Логин (эл. почта)", width: 150)] public string Email { get; set; } = string.Empty; - [DisplayName("Пароль")] + [Column(title: "Пароль", width: 150)] public string Password { get; set; } = string.Empty; } } diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ComponentViewModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ComponentViewModel.cs index 516ff28..40de866 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ComponentViewModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ComponentViewModel.cs @@ -1,4 +1,5 @@ -using FurnitureAssemblyDataModels.Models; +using FurnitureAssemblyContracts.Attributes; +using FurnitureAssemblyDataModels.Models; using System; using System.Collections.Generic; using System.ComponentModel; @@ -10,10 +11,11 @@ namespace FurnitureAssemblyContracts.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: 70)] public double Cost { get; set; } } } diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/FurnitureViewModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/FurnitureViewModel.cs index f0a1775..73abdcd 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/FurnitureViewModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/FurnitureViewModel.cs @@ -1,4 +1,5 @@ -using FurnitureAssemblyDataModels.Models; +using FurnitureAssemblyContracts.Attributes; +using FurnitureAssemblyDataModels.Models; using System; using System.Collections.Generic; using System.ComponentModel; @@ -10,11 +11,13 @@ namespace FurnitureAssemblyContracts.ViewModels { public class FurnitureViewModel : IFurnitureModel { + [Column(visible: false)] public int Id { get; set; } - [DisplayName("Название изделия")] + [Column(title: "Название изделия", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string FurnitureName { get; set; } = string.Empty; - [DisplayName("Цена")] + [Column(title: "Цена", width: 70)] public double Price { get; set; } + [Column(visible: false)] public Dictionary FurnitureComponents { get; set; } = new(); } diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ImplementerViewModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ImplementerViewModel.cs index 117e972..1ec5b16 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ImplementerViewModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/ImplementerViewModel.cs @@ -1,4 +1,5 @@ -using FurnitureAssemblyDataModels.Models; +using FurnitureAssemblyContracts.Attributes; +using FurnitureAssemblyDataModels.Models; using System; using System.Collections.Generic; using System.ComponentModel; @@ -10,15 +11,15 @@ namespace FurnitureAssemblyContracts.ViewModels { public class ImplementerViewModel : IImplementerModel { + [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: 150)] public string Password { get; set; } = string.Empty; - [DisplayName("Опыт работы")] + [Column(title: "Опыт работы", gridViewAutoSize: GridViewAutoSize.AllCells, isUseAutoSize: true)] public int WorkExperience { get; set; } - - [DisplayName("Квалификация")] + [Column(title: "Квалификация", gridViewAutoSize: GridViewAutoSize.AllCells, isUseAutoSize: true)] public int Qualification { get; set; } } } diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/MessageInfoViewModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/MessageInfoViewModel.cs index 98b85aa..60490d2 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/MessageInfoViewModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/MessageInfoViewModel.cs @@ -1,20 +1,24 @@ -using FurnitureAssemblyDataModels.Models; +using FurnitureAssemblyContracts.Attributes; +using FurnitureAssemblyDataModels.Models; using System.ComponentModel; namespace FurnitureAssemblyContracts.ViewModels { public class MessageInfoViewModel : IMessageInfoModel { + [Column(visible: false)] public string MessageId { get; set; } = string.Empty; - + [Column(visible: false)] public int? ClientId { get; set; } - [DisplayName("Отправитель")] + [Column(title: "Отправитель", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string SenderName { get; set; } = string.Empty; - [DisplayName("Дата письма")] + [Column(title: "Дата письма", width: 100)] public DateTime DateDelivery { get; set; } - [DisplayName("Заголовок")] + [Column(title: "Заголовок", width: 170)] public string Subject { get; set; } = string.Empty; - [DisplayName("Текст")] + [Column(title: "Текст", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string Body { get; set; } = string.Empty; + [Column(visible: false)] + public int Id => throw new NotImplementedException(); } } diff --git a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/OrderViewModel.cs b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/OrderViewModel.cs index 77d0e9e..065bfd5 100644 --- a/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/OrderViewModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyContracts/ViewModels/OrderViewModel.cs @@ -1,4 +1,5 @@ -using FurnitureAssemblyDataModels.Enums; +using FurnitureAssemblyContracts.Attributes; +using FurnitureAssemblyDataModels.Enums; using FurnitureAssemblyDataModels.Models; using System; using System.Collections.Generic; @@ -11,27 +12,29 @@ namespace FurnitureAssemblyContracts.ViewModels { public class OrderViewModel : IOrderModel { - [DisplayName("Номер")] + [Column(title: "Номер", width: 50)] public int Id { get; set; } - - public int FurnitureId { get; set; } - [DisplayName("Изделие")] - public string FurnitureName { get; set; } //= string.Empty; - [DisplayName("Количество")] - public int Count { get; set; } - [DisplayName("Сумма")] - public double Sum { get; set; } - [DisplayName("Статус")] - public OrderStatus Status { get; set; } = OrderStatus.Неизвестен; - [DisplayName("Дата создания")] - public DateTime DateCreate { get; set; } = DateTime.Now; - [DisplayName("Дата выполнения")] - public DateTime? DateImplement { get; set; } + [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 int FurnitureId { get; set; } + [Column(title: "Изделие", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] + public string FurnitureName { get; set; } = string.Empty; + [Column(title: "Количество", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] + public int Count { get; set; } + [Column(title: "Сумма", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] + public double Sum { get; set; } + [Column(title: "Статус", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] + public OrderStatus Status { get; set; } = OrderStatus.Неизвестен; + [Column(title: "Дата создания", width: 100)] + public DateTime DateCreate { get; set; } = DateTime.Now; + [Column(title: "Дата выполнения", width: 100)] + public DateTime? DateImplement { get; set; } + [Column(visible: false)] public int? ImplementerId { get; set; } - [DisplayName("Исполнитель")] + [Column(title: "Исполнитель", gridViewAutoSize: GridViewAutoSize.Fill, isUseAutoSize: true)] public string? ImplementerFIO { get; set; } = string.Empty; } } \ No newline at end of file diff --git a/FurnitureAssembly/FurnitureAssemblyDataModels/FurnitureAssemblyDataModels.csproj b/FurnitureAssembly/FurnitureAssemblyDataModels/FurnitureAssemblyDataModels.csproj index c2da37c..27ac386 100644 --- a/FurnitureAssembly/FurnitureAssemblyDataModels/FurnitureAssemblyDataModels.csproj +++ b/FurnitureAssembly/FurnitureAssemblyDataModels/FurnitureAssemblyDataModels.csproj @@ -6,8 +6,4 @@ enable - - - - diff --git a/FurnitureAssembly/FurnitureAssemblyDataModels/Models/IMessageInfoModel.cs b/FurnitureAssembly/FurnitureAssemblyDataModels/Models/IMessageInfoModel.cs index 6139889..b8eb1b3 100644 --- a/FurnitureAssembly/FurnitureAssemblyDataModels/Models/IMessageInfoModel.cs +++ b/FurnitureAssembly/FurnitureAssemblyDataModels/Models/IMessageInfoModel.cs @@ -1,6 +1,6 @@ namespace FurnitureAssemblyDataModels.Models { - public interface IMessageInfoModel + public interface IMessageInfoModel : IId { string MessageId { get; } int? ClientId { get; } diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/DatabaseImplementationExtension.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/DatabaseImplementationExtension.cs new file mode 100644 index 0000000..1364576 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/DatabaseImplementationExtension.cs @@ -0,0 +1,22 @@ +using FurnitureAssemblyContracts.DI; +using FurnitureAssemblyContracts.StoragesContracts; +using FurnitureAssemblyDatabaseImplement.Implements; + +namespace FurnitureAssemblyDatabaseImplement +{ + 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/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/FurnitureAssemblyDatabase.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/FurnitureAssemblyDatabase.cs index 364febb..7461246 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/FurnitureAssemblyDatabase.cs +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/FurnitureAssemblyDatabase.cs @@ -1,29 +1,29 @@ -using FurnitureAssemblyDatabaseImplement.Models; -using Microsoft.EntityFrameworkCore; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace FurnitureAssemblyDatabaseImplement -{ - public class FurnitureAssemblyDatabase : DbContext - { - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - if (optionsBuilder.IsConfigured == false) - { - optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-K0U29OV;Initial Catalog=FurnitureAssemblyDatabaseFull2;Integrated Security=True;MultipleActiveResultSets=True;TrustServerCertificate=True"); - } - base.OnConfiguring(optionsBuilder); - } - public virtual DbSet Components { set; get; } - public virtual DbSet Furnitures { set; get; } - public virtual DbSet FurnitureComponents { set; get; } - public virtual DbSet Orders { set; get; } - public virtual DbSet Clients { set; get; } - public virtual DbSet Implementers { set; get; } - public virtual DbSet Messages { set; get; } - } -} +using FurnitureAssemblyDatabaseImplement.Models; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FurnitureAssemblyDatabaseImplement +{ + public class FurnitureAssemblyDatabase : DbContext + { + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (optionsBuilder.IsConfigured == false) + { + optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-K0U29OV;Initial Catalog=FurnitureAssemblyDatabaseFull2;Integrated Security=True;MultipleActiveResultSets=True;TrustServerCertificate=True"); + } + base.OnConfiguring(optionsBuilder); + } + public virtual DbSet Components { set; get; } + public virtual DbSet Furnitures { set; get; } + public virtual DbSet FurnitureComponents { set; get; } + public virtual DbSet Orders { set; get; } + public virtual DbSet Clients { set; get; } + public virtual DbSet Implementers { set; get; } + public virtual DbSet Messages { set; get; } + } +} diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/FurnitureAssemblyDatabaseImplement.csproj b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/FurnitureAssemblyDatabaseImplement.csproj index cf74c31..55841a6 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/FurnitureAssemblyDatabaseImplement.csproj +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/FurnitureAssemblyDatabaseImplement.csproj @@ -1,24 +1,27 @@ - - - - net6.0 - enable - enable - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - + + + + net6.0 + enable + enable + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/BackUpInfo.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/BackUpInfo.cs new file mode 100644 index 0000000..e2bf4b8 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/BackUpInfo.cs @@ -0,0 +1,26 @@ +using FurnitureAssemblyContracts.StoragesContracts; + +namespace FurnitureAssemblyDatabaseImplement.Implements +{ + public class BackUpInfo : IBackUpInfo + { + public List? GetList() where T : class, new() + { + using var context = new FurnitureAssemblyDatabase(); + 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/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/MessageInfoStorage.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/MessageInfoStorage.cs index bfc5310..50468d4 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/MessageInfoStorage.cs +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Implements/MessageInfoStorage.cs @@ -29,13 +29,18 @@ namespace FurnitureAssemblyDatabaseImplement.Implements return new(); } using var context = new FurnitureAssemblyDatabase(); - return context.Messages.Where(x => x.ClientId.HasValue && x.ClientId == model.ClientId).Select(x => x.GetViewModel).ToList(); + return context.Messages + .Where(x => x.ClientId == model.ClientId) + .Select(x => x.GetViewModel) + .ToList(); } public List GetFullList() { using var context = new FurnitureAssemblyDatabase(); - return context.Messages.Select(x => x.GetViewModel).ToList(); + return context.Messages + .Select(x => x.GetViewModel) + .ToList(); } public MessageInfoViewModel? Insert(MessageInfoBindingModel model) diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Client.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Client.cs index 76914fd..5d55a58 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Client.cs +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Client.cs @@ -8,17 +8,23 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.Serialization; namespace FurnitureAssemblyDatabaseImplement.Models { + [DataContract] public class Client : IClientModel { + [DataMember] public int Id { get; private set; } [Required] + [DataMember] public string ClientFIO { get; private set; } = string.Empty; [Required] + [DataMember] public string Email { get; private set; } = string.Empty; [Required] + [DataMember] public string Password { get; private set; } = string.Empty; [ForeignKey("ClientId")] public virtual List Messages { get; set; } = new(); diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Component.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Component.cs index 1ec3c8a..73634d2 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Component.cs +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Component.cs @@ -4,15 +4,20 @@ using FurnitureAssemblyContracts.ViewModels; using FurnitureAssemblyDataModels.Models; using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; namespace FurnitureAssemblyDatabaseImplement.Models { + [DataContract] public class Component : IComponentModel { + [DataMember] public int Id { get; private set; } [Required] + [DataMember] public string ComponentName { get; private set; } = string.Empty; [Required] + [DataMember] public double Cost { get; set; } [ForeignKey("ComponentId")] public virtual List FurnitureComponents { get; set; } = new(); diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Furniture.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Furniture.cs index 992dc97..ffdfe7d 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Furniture.cs +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Furniture.cs @@ -6,20 +6,26 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; +using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; namespace FurnitureAssemblyDatabaseImplement.Models { + [DataContract] public class Furniture : IFurnitureModel { + [DataMember] public int Id { get; set; } [Required] + [DataMember] public string FurnitureName { get; set; } = string.Empty; [Required] + [DataMember] public double Price { get; set; } private Dictionary? _furnitureComponents = null; [NotMapped] + [DataMember] public Dictionary FurnitureComponents { get diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/FurnitureComponent.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/FurnitureComponent.cs index 67081f0..f91d37d 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/FurnitureComponent.cs +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/FurnitureComponent.cs @@ -14,7 +14,6 @@ namespace FurnitureAssemblyDatabaseImplement.Models public int FurnitureId { get; set; } [Required] public int ComponentId { get; set; } - [Required] public int Count { get; set; } public virtual Component Component { get; set; } = new(); diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Implementer.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Implementer.cs index 2f052b0..35ae83c 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Implementer.cs +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Implementer.cs @@ -6,21 +6,28 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; +using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; namespace FurnitureAssemblyDatabaseImplement.Models { + [DataContract] public class Implementer : IImplementerModel { + [DataMember] public int Id { get; private set; } [Required] + [DataMember] public string ImplementerFIO { get; private set; } = string.Empty; [Required] + [DataMember] public string Password { get; private set; } = string.Empty; [Required] + [DataMember] public int WorkExperience { get; private set; } [Required] + [DataMember] public int Qualification { get; private set; } [ForeignKey("ImplementerId")] public virtual List Orders { get; private set; } = new(); diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/MessageInfo.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/MessageInfo.cs index 1895136..e1f5a99 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/MessageInfo.cs +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/MessageInfo.cs @@ -2,23 +2,27 @@ using FurnitureAssemblyContracts.ViewModels; using FurnitureAssemblyDataModels.Models; using System.ComponentModel.DataAnnotations; +using System.Runtime.Serialization; namespace FurnitureAssemblyDatabaseImplement.Models { + [DataContract] public class MessageInfo : IMessageInfoModel { [Key] + [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 int Id => throw new NotImplementedException(); public virtual Client? Client { get; private set; } diff --git a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Order.cs b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Order.cs index c59d228..e200d62 100644 --- a/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Order.cs +++ b/FurnitureAssembly/FurnitureAssemblyDatabaseImplement/Models/Order.cs @@ -12,30 +12,38 @@ using System.Threading.Tasks; using System.Xml.Linq; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Runtime.Serialization; namespace FurnitureAssemblyDatabaseImplement.Models { + [DataContract] public class Order : IOrderModel { [ForeignKey("ProductId")] + [DataMember] public int FurnitureId { get; set; } [Required] + [DataMember] public int Count { get; set; } [Required] + [DataMember] public double Sum { get; set; } [Required] + [DataMember] public OrderStatus Status { get; set; } [Required] + [DataMember] public DateTime DateCreate { get; set; } - + [DataMember] public DateTime? DateImplement { get; set; } - + [DataMember] public int Id { get; set; } [Required] + [DataMember] public int ClientId { get; private set; } - public virtual Client Client { get; set; } public virtual Furniture Furniture { get; set; } + [DataMember] public int? ImplementerId { get; private set; } public virtual Implementer? Implementer { get; set; } diff --git a/FurnitureAssembly/FurnitureAssemblyFileImplement/FileImplementationExtension.cs b/FurnitureAssembly/FurnitureAssemblyFileImplement/FileImplementationExtension.cs new file mode 100644 index 0000000..9654243 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyFileImplement/FileImplementationExtension.cs @@ -0,0 +1,22 @@ +using FurnitureAssemblyContracts.DI; +using FurnitureAssemblyContracts.StoragesContracts; +using FurnitureAssemblyDatabaseImplement.Implements; + +namespace FurnitureAssemFileImplement +{ + 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/FurnitureAssembly/FurnitureAssemblyFileImplement/FurnitureAssemblyFileImplement.csproj b/FurnitureAssembly/FurnitureAssemblyFileImplement/FurnitureAssemblyFileImplement.csproj index 9a5a60c..1ffafce 100644 --- a/FurnitureAssembly/FurnitureAssemblyFileImplement/FurnitureAssemblyFileImplement.csproj +++ b/FurnitureAssembly/FurnitureAssemblyFileImplement/FurnitureAssemblyFileImplement.csproj @@ -7,14 +7,14 @@ enable - - - - + + + + diff --git a/FurnitureAssembly/FurnitureAssemblyFileImplement/Implements/BackUpInfo.cs b/FurnitureAssembly/FurnitureAssemblyFileImplement/Implements/BackUpInfo.cs new file mode 100644 index 0000000..5231f0e --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyFileImplement/Implements/BackUpInfo.cs @@ -0,0 +1,31 @@ +using FurnitureAssemblyContracts.StoragesContracts; +using FurnitureAssemblyFileImplement; +using System.Reflection; + +namespace FurnitureAssemFileImplement.Implements +{ + public class BackUpInfo : IBackUpInfo + { + public List? GetList() where T : class, new() + { + DataFileSingleton dataFileSingleton = DataFileSingleton.GetInstance(); + return (List?) dataFileSingleton.GetType().GetProperties() + .FirstOrDefault(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericArguments()[0] == typeof(T))? + .GetValue(dataFileSingleton); + } + + 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/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Client.cs b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Client.cs index 620d671..31dce37 100644 --- a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Client.cs +++ b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Client.cs @@ -1,18 +1,21 @@ using FurnitureAssemblyContracts.BindingModels; using FurnitureAssemblyContracts.ViewModels; using FurnitureAssemblyDataModels.Models; +using System.Runtime.Serialization; using System.Xml.Linq; namespace FurnitureAssemblyFileImplement_.Models { + [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) diff --git a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Component.cs b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Component.cs index 7036dec..7d574e8 100644 --- a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Component.cs +++ b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Component.cs @@ -1,14 +1,19 @@ using FurnitureAssemblyContracts.BindingModels; using FurnitureAssemblyContracts.ViewModels; using FurnitureAssemblyDataModels.Models; +using System.Runtime.Serialization; using System.Xml.Linq; namespace FurnitureAssemblyFileImplement.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) diff --git a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Furniture.cs b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Furniture.cs index 80ad7dc..6595cb0 100644 --- a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Furniture.cs +++ b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Furniture.cs @@ -1,17 +1,23 @@ using FurnitureAssemblyContracts.BindingModels; using FurnitureAssemblyContracts.ViewModels; using FurnitureAssemblyDataModels.Models; +using System.Runtime.Serialization; using System.Xml.Linq; namespace FurnitureAssemblyFileImplement.Models { + [DataContract] public class Furniture : IFurnitureModel { + [DataMember] public int Id { get; private set; } + [DataMember] public string FurnitureName { get; private set; } = string.Empty; + [DataMember] public double Price { get; private set; } public Dictionary Components { get; private set; } = new(); private Dictionary? _furnitureComponents = null; + [DataMember] public Dictionary FurnitureComponents { get diff --git a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Implementer.cs b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Implementer.cs index df3a6b4..d823aa0 100644 --- a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Implementer.cs +++ b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Implementer.cs @@ -4,21 +4,25 @@ using FurnitureAssemblyDataModels.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 FurnitureAssemblyFileImplement_.Models { + [DataContract] public class Implementer : IImplementerModel { + [DataMember] public int Id { get; private set; } + [DataMember] public string ImplementerFIO { get; private set; } = string.Empty; - + [DataMember] public string Password { get; private set; } = string.Empty; - + [DataMember] public int WorkExperience { get; private set; } - + [DataMember] public int Qualification { get; private set; } public static Implementer? Create(ImplementerBindingModel? model) diff --git a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/MessageInfo.cs b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/MessageInfo.cs index 875289a..a321042 100644 --- a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/MessageInfo.cs +++ b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/MessageInfo.cs @@ -4,25 +4,29 @@ using FurnitureAssemblyDataModels.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 FurnitureAssemblyFileImplement.Models { + [DataContract] public class MessageInfo : IMessageInfoModel { + [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 int Id => throw new NotImplementedException(); public static MessageInfo? Create(MessageInfoBindingModel model) { diff --git a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Order.cs b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Order.cs index 3913211..d2c5f7e 100644 --- a/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Order.cs +++ b/FurnitureAssembly/FurnitureAssemblyFileImplement/Models/Order.cs @@ -7,30 +7,35 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; +using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; namespace FurnitureAssemblyFileImplement.Models { + [DataContract] public class Order : IOrderModel { + [DataMember] public int FurnitureId { get; private set; } - + [DataMember] public string FurnitureName { get; private set; } = string.Empty; - + [DataMember] public int Count { get; private set; } - + [DataMember] public double Sum { get; private set; } - + [DataMember] public OrderStatus Status { get; private set; } = OrderStatus.Неизвестен; - + [DataMember] public DateTime DateCreate { get; private set; } = DateTime.Now; - + [DataMember] public DateTime? DateImplement { get; private set; } + [DataMember] public int ClientId { get; private set; } - + [DataMember] public int Id { get; private set; } + [DataMember] public int? ImplementerId { get; private set; } = null; public static Order? Create(OrderBindingModel? model) diff --git a/FurnitureAssembly/FurnitureAssemblyListImplement/FurnitureAssemblyListImplement.csproj b/FurnitureAssembly/FurnitureAssemblyListImplement/FurnitureAssemblyListImplement.csproj index 04d3de8..b8b6f05 100644 --- a/FurnitureAssembly/FurnitureAssemblyListImplement/FurnitureAssemblyListImplement.csproj +++ b/FurnitureAssembly/FurnitureAssemblyListImplement/FurnitureAssemblyListImplement.csproj @@ -6,14 +6,14 @@ enable - - - - + + + + diff --git a/FurnitureAssembly/FurnitureAssemblyListImplement/Implements/BackUpInfo.cs b/FurnitureAssembly/FurnitureAssemblyListImplement/Implements/BackUpInfo.cs new file mode 100644 index 0000000..b099c9c --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyListImplement/Implements/BackUpInfo.cs @@ -0,0 +1,18 @@ +using FurnitureAssemblyContracts.StoragesContracts; + + +namespace FurnitureAssemblyListImplement.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/FurnitureAssembly/FurnitureAssemblyListImplement/ListImplementationExtension.cs b/FurnitureAssembly/FurnitureAssemblyListImplement/ListImplementationExtension.cs new file mode 100644 index 0000000..8f39b42 --- /dev/null +++ b/FurnitureAssembly/FurnitureAssemblyListImplement/ListImplementationExtension.cs @@ -0,0 +1,22 @@ +using FurnitureAssemblyContracts.DI; +using FurnitureAssemblyContracts.StoragesContracts; +using FurnitureAssemblyListImplement.Implements; + +namespace FurnitureAssemblyListImplement +{ + 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/FurnitureAssembly/FurnitureAssemblyListImplement/Models/MessageInfo.cs b/FurnitureAssembly/FurnitureAssemblyListImplement/Models/MessageInfo.cs index 332bb9f..96e81a9 100644 --- a/FurnitureAssembly/FurnitureAssemblyListImplement/Models/MessageInfo.cs +++ b/FurnitureAssembly/FurnitureAssemblyListImplement/Models/MessageInfo.cs @@ -17,6 +17,7 @@ namespace FurnitureAssemblyListImplement.Models public string Subject { get; private set; } = string.Empty; public string Body { get; private set; } = string.Empty; + public int Id => throw new NotImplementedException(); public static MessageInfo? Create(MessageInfoBindingModel model) { diff --git a/FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyContracts.dll b/FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyContracts.dll new file mode 100644 index 0000000000000000000000000000000000000000..573ed6dee778b34b64606e2a6d04d1ea0f68a6cf GIT binary patch literal 32256 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 literal 0 HcmV?d00001 diff --git a/FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyDataModels.dll b/FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyDataModels.dll new file mode 100644 index 0000000000000000000000000000000000000000..2dc18229f3c57dc159ed8b2c10424916015b6436 GIT binary patch literal 7168 zcmeHLYiu0V6+W{wyWZHbiIbQZLdXOs#YtdU+lhlIG=8iN3vujZje+9UncW>bLuO}I zGqXwD2Qf)Nr7a}|genAtN|lN#6`_>05l_*oD1D%=D^bz@=tEV7P=5fGDhjPgzjJ4H zcQ&ReN`Dn`?fcDn-E+@9_c3#K^s~oECL#s(%o(Cncyj3%cy5@7x@GONE%eNiSJ$1A zcD%Z7Vz1$iT#pYE?T}=e+nl(s z(%T>DGPOxc5-o=$?n?*3l8V}oO0-PS5kGDgaQvdo10m-k)1JH8l>ckbfMpTNTUQZ{ zG0{)7zUqVpLD@sJ6y&J{(L_b|QJ!iwbYUF_e?zEU!qX3W;BVmApc7*a;sz&*O0*~8 zxK0k7h^-$)40R=HsPrTHgrl1_3^`WXgUY@xMh%sIqQMX=$PUgc3da_qC_SX2uNESS zh38Q&i*z;vgqioH9=gyUKjIeoha7swNC+J-gdw4EV1m3GK zno?12q>JcQ_*qIUkp#9w9-~7t<4*$G?n9h;b`u zg}#l9xpXyBC}W(=ZIs&t7ZY4>z%3Enn-O2vB)C<9u0?R~1-j*eYYKGjBq5v^lnG@Q zdQcJL+wyh5pGO8L78|D&P0nwMUJu+ZaEHK^0@nh^RUXql?N5r4-&W;zVJuFSn*?{b z%CXKbuQVT^sSr1a?NZZ?$YJieI$cZ(>)uiFp>}_%vph{<-6P80kmXgd^j8VdE6v

3*h!dw9Q&`+8k}Zz$pZ4#@eCmlMj-5SNs~ zJ-nve8`3>h=kw7}oG~0+4XAO{C8$l}`6TvAEAd=j1Z<>@z-81WuutHCz_h?!0&f$j z0b?`=Y$HR^ajez#!v98KJ0*aZP!CY0tD(7={vmC^QF{|KO>`Q#f);?Q>1|*Ky$9S( z+oS~A+zR|O<$yy}1l}a%8Q>7z4!a?oatRt1-f}{c6OtU|=sS`w#zF{1?*Q zLjDuFjQ%G5S)eR2-63$J#1Re&I*K(DLtY!O2jjpc@X|;vB5VAfegMmPgdPUoC^Nn! z=tha@zblUb-xQKx64Q?>j{|#z#JBv7@bDFx{TvqZ6ZC!1{}gmX^d#t4754Ulz+=Mx zuL|3LQD&b%R-OfJk=XLL%1gi#!sZG1;dhA)jN!>+XaL4Bh6rjCuo0(d1k?q*Hz!f-$BUm--fNhws2#)Fvz*TfPupMhBf;O9h7t@u% z)pQl`60D{O+V=o2B|hWU(l%1&aqJ=HTHzB9uajz7P3wd~y=*_Mg0iz@np)P>_jJ*u zW|s7cQV~oyrHq_s*p}wZfw^|n&X-L6Gc>Dv)9C^%3cBU#&PaMph=xo9JahZm$MiI1 z=3GxNB!+C$)P*BAalLNoj*+8uI`8}OAEUbKYO{JE94R@L;gy^UAL=Zy@cRmwam{rP z*pBaM9Nu-|`WD;SH+-;&?sO{QdNy^<^fkZO6l3s>?}`0O;(wf znqPW=C#r7kJW>R-tOy*)`+M2PQf+l9#{Et>cwl!nS zmK`T1S7&n6{V{S0Bcz{DP382$Uq<&bFdx)I<)QriNEeDOl7h7Jgk@IY)B2O9G ztYy2Nk#j4eAVJu0{_@M{&VK9$H&|TA00-exCH0&wmqv}8W4rc@hjw{=z|zb)*Kp4{ z2!AZ+GC7wn!2_-a9XcJTI@kV!c12dI+2mn~&FRZCp5~QY5)&5CoWx8idk0RN>L#sD zqL2*P*uw$k`oy4}pQ~D@bko?cJ9AWiu>9h};qr^+6I6a+;cMk*%1@VHpz>qoljT$8 zAC*s(PcGaA{Ye%cUzmsRg@yYU4*SM0q1|&VfYo8x-S3~XpS%B?$6o%|J2(B{o!`f8^E@vrMRL}>nKAKmpYcTj>?^A z)rnS}Xw_NY3an_=$*lm%xG!lPjZ1hXa=Dbh&nF@m-r{J*owhZ6FsB#!See-C*aut* zb`2uV>m+JV>>QpLvK@V(SiBg!`~T&f-`G>+L{S`}RPdDvY{t4u8}m7fKC%`_HV$}~qc!=i$l!|Kz; zfh@FVHo(c*sa)*w6UqNU1|%_&?L_nS!TMVc>t&Ig?fAE&Tl=xUcy|Wnw7dn>BxPtC zI83`irSVJKPVi~qi2th_eg$~z1OGdmcN!P}x!q@ok8s}K;gSL)!K+3N{22H>NQY00 zX2=$1>qV;xXf;S(=r!_SXM^+0(@G~|l@OB$D+BV`5AnqB3yG4|zb%vnjj`fJA>saK zQ-O-2k2#D;1E&l3BUFM{3w}L8=`?^STxbjMVB*G_5)o-M3LkmMO=yYs2)~sPr66~4 zXXN;bb@89C|0G^FQgxh@@b939T3)(vpG{UP$D_iYGwTUk3sIY)k)B^135?jpA5kY} z7Uw^F&kE0+(IT?LBc7$b=#>xwf#NvE0y)nX$5F`>bAIOk*LeJS9Y;SrD<$OK3yqd< z+vhj0hj9y)sNV0{*{|h(GsdG~9{O-c?LrJ1)^(D)@%u#{d@rOrs6N^PsSbWCq}xE} zVbcT50X1l5K=FFbBZGw2Jojg>LlwKIeihW>;I;5c`PgRwlZ>ClDfP)@f9$9F!v^?o DES`@j literal 0 HcmV?d00001 diff --git a/FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyFileImplement.dll b/FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyFileImplement.dll new file mode 100644 index 0000000000000000000000000000000000000000..4a608bc0baa6dfbbf2cb230425ece5dddf4cb73e GIT binary patch literal 41472 zcmeHw3wTu3wf{P2X3k6|nItoL@-#dh3B&}VLPbl2AgO=|h)_isk|9Kr49o-pku(vs z;-i(;+S;lG!M4<@#agwBnpCQ#)e2Sbl|D)FQCh3jwzs!h@&8+E@AH@>_TI0(|Nr;> zzwbt8o%Pylt-bf!kF(F2VcsWiAs-R>@%ivWqDOJ%zZnAmG3bIg|CGn_>7ktGM?GrH zeSXy9H7%Knb?H=dI?-0qm}qZLbyTcMR-`wySG2TO%(`$WStW zKAL~S;SX$Y$7pm#u2D_&C2&HD`|!iKR^Zcv4^g4uriz;x9KZTAh`{GRAFaHWRr!DS zs!3+yF9Ew3GSY)MTqDd;f5(XOfQ|hw(PGW|Z(S;!&_z82dXA@HRY!7D2j~O00YD~o z)p3K8zY3z2Rq0H+5tPK%1H{7T%lLTyW}v&O(#h5o6ggHph7a4?g^%ZN2GMyQQqV7O zyW)>yGbuoiE+T485TOmfbuP=Ejx!?$`>W{t4&W0^a}{G5aTs zG`Aoj{S!u;zO90QfsRoOLBI&u3_-v^vnUNgh>EIxG#531%P5(}CylT*F+jz+mD4jZ zG~zfjg-bXEZHqt@F@aPQqL_)WCQ6tNx=z4)qc8pFuPl|-84L|i34ueiPEo$c#eKyT_He4WgW7Mhm~(Z45Kcel>rH+Yn})Ls0z87?hgu zHM4Upu3I@zG|CyGQO*rBJ`M`RX@;7qoDl>JG>~El0tVbFh9F>|)f7VzFc5%Z2%_?C z8QK7uo1J$J946=8c(~^-kW@pThEqruA>vFRUxYY~2_%6K6PQ5f=p=-F&O;u$UOyq^ z_tZULYFBQn_fJLbK7GF3QS3>lqK?LGWsgh;mrf2Wr*d2eoZj|P3f@X^zSbe!e)(F9 ztmJm#L1YmKZkM>Y2EpwT7dIfdUE*RAn2dSUNd7XF5FvXpu&vZY;GD|Hbt^SV6BwOV zs!9_WpjPU1O<)jODJ(yBUUQQop`z)p+O--sNM5t2?7VhbS9#X?Tkf{38RsB0e~8kry-LQ*kXlX;d1e zxj~-KBbAleF=9-3VjMTgKfbs!5LXefcdqLV@Ev5|k7(bhAN%Hu>w8j6b1<8!Xex~| zc+H{A$2gkGIoX~cbvz@VD?1UXf83<9@tp|Wf71FkOHsM-xGt8&eb9*`sVeg-DTGGh zxL}sIJD4}zX77Y|ubus_9hSIu!j)u+9Y5U!JLq++0UkrCk8{&i`^qY7JlszB^qPN= z&Cif9S;8wpW!ciydEk&Q9)UD$VPR2?pNFNzjnqmZrNVaX()E^fz0{EFcNyXebGv^} z?D)2x3m0|)onw!209iR^AjhPqM+dDfTq0Ef9lKaoilKx1XE;JehO721McQJTj%Iqa ze+10^&X?3I#HMoYRL!Xe$IdxU22q=BtEm*klpC1}bG8+4nIeDGKXD=gmT|A9RW4X^8`|ADFuOzxu%s0+q? zG;!1011R@pfNX~$Z&6*PqFz6BuhtrJJAGF^HCwp=>r|< zIXzs4eX&VP;7|VI7otFE3S+I3G>)8daM*Eh^pAt1O&lC?J2>``m4y2Ny>pWsnFmMU zM@bg4u$8(9E>jBuIu`**$}I+R(z+NhgV2z2EQ!ZpO^rLtieCaw2Vxi|n|s*gdaS?| zT2VTTZa3pgp_5t$056}!C6|JErIE_Xp`0%l`6=p8T?*#J!l>Vu!VDKKjxPta$7>J@ zMOI}Y<&-UrM1U(~nJc58xYBK}@qs(Rq0!F#b5Cn`NHbW3F zhT054RNcmK9l36usI_0+BjiyAgTm@!j^aye{K|}D?Xt`*=of$b5$t_Bp{7O&hA>9+ z3!FTcqqgI^Si+kvbQH>A^MG>bAAkCJE{BoiEq9p9p_NgNC2?#=Rk>+W4t?)WALnuy zZ{Bi8xZFx9#}eMpsdBt{m|M_i{`5Os4%y)?_fsy1(Exue;fEPnK)LzZ z0e{F&)VD7clI z)=W1r%C$Dr%NgZ{Gt-+HY$f7kR}O) zCA_VyC4HmjFBHbQ6TbplI5DULx|R#bKC(LA>fmF2a*rQx zb2u@7922s4Nw3VU3}xD(peGl;M@EAX(pK&beeh6CW%^!1(lTrY;-fgM(EzzY+0@^i zSqB@w_|K@>v}_~i8f*-l7(@$H<4oSs>V7QlUJ8s>SX zmmAIu6G#~$I+#G8+IOFP?|J25wpMFfAARGg?Wc3if#)3BUHa64viOF6A;>&^Dq=9X zK0fEHV<>J4Irg|11HrM!CH4sqXAm^s6JidqQX7HuJs}3DmD;2Uq`Q^c%)|s~GmFss zgkc{|^YD@`A2P_jA6v}6_j4+!Jh=CMcIC`CJL7w}tKd(`)jiyNedES`X|H+cQe>;@ zQbE8#wkd`nU{u%)LBK#JDGfnn{=uN3a>;=$NHM(tT$p(cv0z;#gWLx3W>}N%*4oI~IKwJ~8uT=iR4x)N|f- zqAahgl4_q~;xbKiF>$#jxK5RB_$N$0X`@vmJmOX6b@U}`1XQv;I6 z<8S)KCTA!wfT_d#=v3Arr)%sU^_-LF8l>k9l&MtKwMs9`Qb>0@B+o0IaN(`)F|N-x zsV+-8FU=PBxnh>^ZYis}(*J1f{$pl6h6%TOT%rci#e_r%LfRb?Zy;ziyWLsRxjb8p zrP~&>MA|*R5=dP});#--C!CU4*RjmvRE+>X-Y0?p%XkylYBvjYK+>tacK zJlZ~c4#(&SPqnKK5vv>wOwAIKJ1Vb6Qs~CcSf!)EUKHXpOkl

bcKv(PINgYM{aYu&f*>lXE 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 b`}hBC3w&Gs`%#ac`TuPV{x|S{p#}aAr4>Ln literal 0 HcmV?d00001 diff --git a/FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyListImplement.dll b/FurnitureAssembly/ImplementationExtensions/FurnitureAssemblyListImplement.dll new file mode 100644 index 0000000000000000000000000000000000000000..cfb39b154b61b5b530933207378d1b3880347291 GIT binary patch literal 26112 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 lQnold3Vv{o{O{*~Yy<|>|7S#%{N>L7*irni