Compare commits

..

1 Commits

Author SHA1 Message Date
bekodeg
63577d725c изменения для отчёта 2025-01-17 21:20:54 +04:00
56 changed files with 421 additions and 2010 deletions

View File

@ -11,10 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lab3", "Lab3\Lab3.csproj",
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lab3.Database", "Lab3.Database\Lab3.Database.csproj", "{698DE9E8-7885-4F98-AFE3-9A9C6CD2FCF5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lab3.Database", "Lab3.Database\Lab3.Database.csproj", "{698DE9E8-7885-4F98-AFE3-9A9C6CD2FCF5}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lab4", "Lab4\Lab4.csproj", "{FAE92C0B-0A2D-48B6-A55C-DE58A310CD58}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lab4.Plugins", "Lab4.Plugins\Lab4.Plugins.csproj", "{F30C8C78-98CB-4C5E-BEE8-125791A9D7AF}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -37,14 +33,6 @@ Global
{698DE9E8-7885-4F98-AFE3-9A9C6CD2FCF5}.Debug|Any CPU.Build.0 = Debug|Any CPU {698DE9E8-7885-4F98-AFE3-9A9C6CD2FCF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{698DE9E8-7885-4F98-AFE3-9A9C6CD2FCF5}.Release|Any CPU.ActiveCfg = Release|Any CPU {698DE9E8-7885-4F98-AFE3-9A9C6CD2FCF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{698DE9E8-7885-4F98-AFE3-9A9C6CD2FCF5}.Release|Any CPU.Build.0 = Release|Any CPU {698DE9E8-7885-4F98-AFE3-9A9C6CD2FCF5}.Release|Any CPU.Build.0 = Release|Any CPU
{FAE92C0B-0A2D-48B6-A55C-DE58A310CD58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FAE92C0B-0A2D-48B6-A55C-DE58A310CD58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FAE92C0B-0A2D-48B6-A55C-DE58A310CD58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FAE92C0B-0A2D-48B6-A55C-DE58A310CD58}.Release|Any CPU.Build.0 = Release|Any CPU
{F30C8C78-98CB-4C5E-BEE8-125791A9D7AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F30C8C78-98CB-4C5E-BEE8-125791A9D7AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F30C8C78-98CB-4C5E-BEE8-125791A9D7AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F30C8C78-98CB-4C5E-BEE8-125791A9D7AF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -41,7 +41,7 @@ namespace Cop.Borovkov.Var3.Components
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells; column.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
} }
_ = outDataGridView.Columns.Add(column); outDataGridView.Columns.Add(column);
} }
} }
@ -108,10 +108,10 @@ namespace Cop.Borovkov.Var3.Components
Type type = typeof(TType); Type type = typeof(TType);
for (int i = 0; i < insertValues.Count; ++i) for (int i = 0; i < insertValues.Count(); ++i)
{ {
var row = insertValues[i]; var row = insertValues[i];
_ = outDataGridView.Rows.Add(); outDataGridView.Rows.Add();
for (int j = 0; j < outDataGridView.ColumnCount; ++j) for (int j = 0; j < outDataGridView.ColumnCount; ++j)
{ {

View File

@ -3,10 +3,12 @@ using PIHelperSh.PdfCreator;
using PIHelperSh.PdfCreator.Enums; using PIHelperSh.PdfCreator.Enums;
using PIHelperSh.PdfCreator.Models.PieChartModel; using PIHelperSh.PdfCreator.Models.PieChartModel;
using System.ComponentModel; using System.ComponentModel;
using static System.Runtime.InteropServices.Marshalling.IIUnknownCacheStrategy;
namespace Cop.Borovkov.Var3.Components namespace Cop.Borovkov.Var3.Components
{ {
/// <summary>
/// Компонент создающий линейную диаграмму
/// </summary>
public partial class CustomPdfHistogram : Component public partial class CustomPdfHistogram : Component
{ {
public CustomPdfHistogram() public CustomPdfHistogram()

View File

@ -0,0 +1,36 @@
namespace Cop.Borovkov.Var3.Components
{
partial class CustomPdfTable
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@ -0,0 +1,92 @@
using Cop.Borovkov.Var3.Models;
using PIHelperSh.PdfCreator;
using PIHelperSh.PdfCreator.Enums;
using PIHelperSh.PdfCreator.Interfaces;
using PIHelperSh.PdfCreator.Models.TableModels;
using System.ComponentModel;
namespace Cop.Borovkov.Var3.Components
{
/// <summary>
/// Компонент для сохранения таблицы в пдф
/// </summary>
public partial class CustomPdfTable : Component
{
/// <summary>
/// </summary>
public CustomPdfTable()
{
InitializeComponent();
}
/// <summary>
/// </summary>
/// <param name="container"></param>
public CustomPdfTable(IContainer container)
{
container.Add(this);
InitializeComponent();
}
/// <summary>
/// Сохранить набор таблиц в пдф
/// </summary>
/// <param name="fileName"></param>
/// <param name="title"></param>
/// <param name="tables"></param>
public void SaveToPdf(PdfTableInfo tableInfo)
{
if (!tableInfo.Tables.Any())
{
return;
}
PdfCreator creator = new PdfCreator();
creator.AddParagraph(new()
{
Style = PdfStyleType.Title,
Text = tableInfo.Title,
MarginAfter = PdfMargin.Smal,
});
foreach (string[,] table in tableInfo.Tables)
{
List<PDFSimpleTableRow> rows = new();
for (int i = 0; i < table.GetLength(0); ++i)
{
PDFSimpleTableRow row = new();
for (int j = 0; j < table.GetLength(1); ++j)
{
row.Items.Add(table[i, j]);
}
rows.Add(row);
}
creator.AddSimpleTable(new()
{
Header = rows.First().Items.Select(item => new PdfTableColumn()
{
Title = item,
Size = 3,
} as IPdfColumnItem).ToList(),
Rows = rows.Skip(1).ToList(),
HeaderStyle = PdfStyleType.Basic,
HeaderHorizontalAlignment = PdfAlignmentType.Left,
RowHorizontalAlignment = PdfAlignmentType.Left,
});
creator.AddParagraph(new()
{
MarginAfter = PdfMargin.Smal,
});
}
creator.SavePdf(tableInfo.FilePath);
}
}
}

View File

@ -1,13 +1,28 @@
namespace Cop.Borovkov.Var3.Models namespace Cop.Borovkov.Var3.Models
{ {
/// <summary>
/// Параметры столбца таблицы
/// </summary>
public record CustomDataTableColumnParameter public record CustomDataTableColumnParameter
{ {
/// <summary>
/// Заголовок
/// </summary>
public string HeaderName { get; init; } = string.Empty; public string HeaderName { get; init; } = string.Empty;
/// <summary>
/// Ширина
/// </summary>
public int Width { get; init; } = 0; public int Width { get; init; } = 0;
/// <summary>
/// Видимость
/// </summary>
public bool Visible { get; init; } = true; public bool Visible { get; init; } = true;
/// <summary>
/// Название свойства
/// </summary>
public string PropertyName { get; init; } = string.Empty; public string PropertyName { get; init; } = string.Empty;
} }
} }

View File

@ -31,5 +31,5 @@ namespace Cop.Borovkov.Var3.Models
/// Значения /// Значения
/// </summary> /// </summary>
public required IEnumerable<PdfHistogramLineInfo> Values { get; init; } public required IEnumerable<PdfHistogramLineInfo> Values { get; init; }
} }
} }

View File

@ -0,0 +1,23 @@
namespace Cop.Borovkov.Var3.Models
{
/// <summary>
/// Параметры для создания таблиц в пдф
/// </summary>
public record PdfTableInfo
{
/// <summary>
/// имя файла (включая путь до файла)
/// </summary>
public string FilePath { get; init; } = @"C:\pdfTable.pdf";
/// <summary>
/// название документа(заголовок в документе)
/// </summary>
public string Title { get; init; } = "Таблица";
/// <summary>
/// Список таблиц
/// </summary>
public IEnumerable<string[,]> Tables { get; init; } = [];
}
}

View File

@ -18,7 +18,7 @@ namespace PIHelperSh.PdfCreator.Models.PieChartModel
public IEnumerable<(string Name, double Value)> Value { get; set; } public IEnumerable<(string Name, double Value)> Value { get; set; }
/// <summary> /// <summary>
/// Цвет области на диаграмме. При null будет использоваться выдача цветов по умолчанию) /// Цвет области на диаграме. При null будет использоваться выдача цветов по умолчанию)
/// </summary> /// </summary>
public Color? Color { get; set; } = null; public Color? Color { get; set; } = null;

View File

@ -18,7 +18,7 @@ namespace PIHelperSh.PdfCreator.Models.PieChartModel
public double Value { get; set; } public double Value { get; set; }
/// <summary> /// <summary>
/// Цвет области на диаграмме. При null будет использоваться выдача цветов по умолчанию) /// Цвет области на диаграме. При null будет использоваться выдача цветов по умолчанию)
/// </summary> /// </summary>
public Color? Color { get; set; } = null; public Color? Color { get; set; } = null;

View File

@ -34,7 +34,7 @@ namespace PIHelperSh.PdfCreator.Models.TableModels
public PdfStyleType RowStyle = PdfStyleType.Basic; public PdfStyleType RowStyle = PdfStyleType.Basic;
/// <summary> /// <summary>
/// Базовое выравнивание элементов в строке /// Базовое выравнивание элементов сторок
/// </summary> /// </summary>
public PdfAlignmentType RowHorizontalAlignment = PdfAlignmentType.Rigth; public PdfAlignmentType RowHorizontalAlignment = PdfAlignmentType.Rigth;

View File

@ -13,7 +13,7 @@ namespace PIHelperSh.PdfCreator.Models.TableModels
public class PDFSimpleTableRow public class PDFSimpleTableRow
{ {
/// <summary> /// <summary>
/// Элементы данной стоки /// Элемменты данной стоки
/// </summary> /// </summary>
public List<string> Items = new List<string>(); public List<string> Items = new List<string>();

View File

@ -35,7 +35,7 @@ namespace PIHelperSh.PdfCreator.Models.TableModels
public PdfStyleType RecordStyle { get; set; } = PdfStyleType.Basic; public PdfStyleType RecordStyle { get; set; } = PdfStyleType.Basic;
/// <summary> /// <summary>
/// Выравнивание текста объектов в таблице (по умолчанию - по левой стороне) /// Выравнивание текста объектов в таблице (по умолчанию - по левой строне)
/// </summary> /// </summary>
public PdfAlignmentType RecordHorizontalAlignment { get; set; } = PdfAlignmentType.Left; public PdfAlignmentType RecordHorizontalAlignment { get; set; } = PdfAlignmentType.Left;

View File

@ -1,5 +1,10 @@
using PIHelperSh.PdfCreator.Enums; using PIHelperSh.PdfCreator.Enums;
using PIHelperSh.PdfCreator.Interfaces; using PIHelperSh.PdfCreator.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PIHelperSh.PdfCreator.Models.TextModels namespace PIHelperSh.PdfCreator.Models.TextModels
{ {

View File

@ -14,7 +14,7 @@ namespace Lab3.Database.Extensions
this IServiceCollection services, this IServiceCollection services,
IConfiguration configuration) IConfiguration configuration)
{ {
_ = services.AddDbContextPool<COPContext>( services.AddDbContextPool<COPContext>(
dbContextOptions => dbContextOptions =>
{ {
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);

View File

@ -21,7 +21,7 @@ namespace Lab3.Extensions
return services; return services;
} }
public static IServiceCollection AddLab3Forms( public static IServiceCollection AddForms(
this IServiceCollection services) this IServiceCollection services)
{ {
services.AddScoped<MainForm>(); services.AddScoped<MainForm>();

View File

@ -19,7 +19,7 @@ namespace Lab3.Forms
var values = (await _repository.Get()).ToList(); var values = (await _repository.Get()).ToList();
for (int i = 0; i < values.Count; i++) for (int i = 0; i < values.Count; i++)
{ {
_ = Catalog.Rows.Add(); Catalog.Rows.Add();
Catalog.Rows[i].Cells[0].Value = values[i]; Catalog.Rows[i].Cells[0].Value = values[i];
} }
} }
@ -40,7 +40,7 @@ namespace Lab3.Forms
string? val = (string?)Catalog.Rows[i].Cells[0].Value; string? val = (string?)Catalog.Rows[i].Cells[0].Value;
if (string.IsNullOrEmpty(val)) if (string.IsNullOrEmpty(val))
{ {
_ = MessageBox.Show( MessageBox.Show(
"Неверные данные", "Неверные данные",
"Ошибка", "Ошибка",
MessageBoxButtons.OK, MessageBoxButtons.OK,
@ -54,7 +54,7 @@ namespace Lab3.Forms
} }
catch (Exception ex) catch (Exception ex)
{ {
_ = MessageBox.Show( MessageBox.Show(
ex.Message, ex.Message,
"Ошибка", "Ошибка",
MessageBoxButtons.OK, MessageBoxButtons.OK,
@ -66,7 +66,7 @@ namespace Lab3.Forms
{ {
if (e.KeyCode == Keys.Insert) if (e.KeyCode == Keys.Insert)
{ {
_ = Catalog.Rows.Add(); Catalog.Rows.Add();
} }
if (e.KeyCode == Keys.Delete && Catalog.SelectedRows.Count == 1) if (e.KeyCode == Keys.Delete && Catalog.SelectedRows.Count == 1)
@ -84,7 +84,7 @@ namespace Lab3.Forms
} }
catch (Exception ex) catch (Exception ex)
{ {
_ = MessageBox.Show( MessageBox.Show(
ex.Message, ex.Message,
"Ошибка", "Ошибка",
MessageBoxButtons.OK, MessageBoxButtons.OK,

View File

@ -37,7 +37,7 @@ namespace Lab3.Forms
} }
var student = await _studentRepository.GetAsync(_updatedStudentGuid.Value); var student = await _studentRepository.GetAsync(_updatedStudentGuid.Value);
NameTextBox.Text = student!.Name; NameTextBox.Text = student.Name;
StartEducationDataPicker.Value = student.StartEducation; StartEducationDataPicker.Value = student.StartEducation;
FormSelector.ComboBoxSelectedValue = student.EducationForm; FormSelector.ComboBoxSelectedValue = student.EducationForm;
@ -101,11 +101,11 @@ namespace Lab3.Forms
if (_updatedStudentGuid != null) if (_updatedStudentGuid != null)
{ {
_ = await _studentRepository.UpdateAsync(student); await _studentRepository.UpdateAsync(student);
} }
else else
{ {
_ = await _studentRepository.CreateAsync(student); await _studentRepository.CreateAsync(student);
} }
Close(); Close();
} }

View File

@ -1,4 +1,5 @@
using Lab3.Database.DTO; using Lab3.Database.DTO;
using System.Globalization;
namespace Lab3.Models namespace Lab3.Models
{ {

View File

@ -9,7 +9,7 @@ namespace Lab3
internal static class Program internal static class Program
{ {
/// <summary> /// <summary>
/// The main entry point for the application. /// The main entry point for the application.
/// </summary> /// </summary>
[STAThread] [STAThread]
static void Main() static void Main()
@ -34,7 +34,7 @@ namespace Lab3
services.AddMapping(); services.AddMapping();
services.AddLab3Forms(); services.AddForms();
}); });
} }
} }

View File

@ -1,20 +0,0 @@
using Lab4.Interfaces;
using Lab4.Plugins.Implementations;
using Microsoft.Extensions.DependencyInjection;
namespace Lab4.Plugins.Extensions
{
public static class DiExtensions
{
public static IServiceCollection AddScopes(
this IServiceCollection services)
{
services.AddScoped<PluginsConvention>();
services.AddScoped<Func<Type, IPluginsConvention>>(sp
=> (type) => (sp.GetRequiredService(type) as IPluginsConvention)!);
return services;
}
}
}

View File

@ -1,223 +0,0 @@
using Lab4.Plugins.Models;
using AutoMapper;
using Lab3.Database.Repository.Interfaces;
using Cop.Borovkov.Var3.Components;
using CustomComponentsVar2;
using ComponentsLibrary;
using System.Windows.Forms;
using ComponentsLibrary.entities;
using ComponentsLibrary.entities.enums;
using Lab3.Database.DTO;
using Lab3.Forms;
using Lab3.Models;
using Lab4.Interfaces;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Lab3.Extensions;
using Microsoft.Extensions.DependencyInjection;
namespace Lab4.Plugins.Implementations
{
public class PluginsConvention : IPluginsConvention
{
private readonly IMapper _mapper;
private readonly IStudentRepository _studentRepository;
private readonly IEducationFormRepository _educationFormRepository;
private readonly CustomListBox _control;
private readonly CustomPdfTable _simpleDocumentCreator;
private readonly CustomExcelTable _tableCreator;
private readonly ComponentDiagram _chartCreator;
public PluginsConvention()
{
_control = new();
_chartCreator = new();
_tableCreator = new();
_simpleDocumentCreator = new();
var serviceProvider = CreateServiceProvider();
_mapper = serviceProvider.GetRequiredService<IMapper>();
_studentRepository = serviceProvider.GetRequiredService<IStudentRepository>();
_educationFormRepository = serviceProvider.GetRequiredService<IEducationFormRepository>();
}
public string PluginName => "Успеваемость";
public UserControl GetControl => _control;
public PluginsConventionElement GetElement
{
get
{
var filds = _control.Selected.Split();
Guid id = Guid.Parse(filds[0]);
return new()
{
Id = id,
};
}
}
public bool CreateChartDocument(PluginsConventionSaveDocument saveDocument)
{
try
{
var data = _studentRepository.GetAsync().Result
.GroupBy(s => s.EducationForm)
.Select(s => new DataLine(
s.Key,
s.GroupBy(x => x.StartEducation.Year)
.Select(x => (year: x.Key.ToString(), count: (double)x.Count()))
.ToArray()))
.ToList();
_chartCreator.AddDiagram(
new(
saveDocument.FileName,
"Поступления",
"Диаграмма",
EnumAreaLegend.Bottom,
data
)
);
return true;
}
catch
{
return false;
}
}
public bool CreateSimpleDocument(PluginsConventionSaveDocument saveDocument)
{
try
{
var values = _studentRepository.GetAsync().Result
.Select(s => s.StudentSessions
.OrderBy(x => x.Number)
.Select(x => x.Score.ToString())
.ToArray())
.ToArray();
var tables = new string[values.Length, 6];
for (int i = 0; i < values.Length; ++i)
{
for (int j = 0; j < 6; ++j)
{
tables[i, j] = values[i][j];
}
}
_simpleDocumentCreator.SaveToPdf(new()
{
FilePath = saveDocument.FileName,
Title = "Сессии",
Tables = [tables]
});
return true;
}
catch
{
return false;
}
}
public bool CreateTableDocument(PluginsConventionSaveDocument saveDocument)
{
try
{
_tableCreator.SaveToExcel<StudentDTO>(new()
{
FilePath = saveDocument.FileName,
Title = "Студенты",
Headers =
[
("Id", nameof(StudentDTO.Id)),
("ФИО", nameof(StudentDTO.Name)),
("Форма обучения", nameof(StudentDTO.EducationForm)),
("Дата поступления", nameof(StudentDTO.StartEducation)),
],
HeaderGroups = [new() {
GroupHeader = "Образование",
FirstHeader = 2,
LastHeader = 3,
}],
Values = _studentRepository.GetAsync().Result
});
return true;
}
catch
{
return false;
}
}
public bool DeleteElement(PluginsConventionElement element)
{
try
{
_studentRepository
.DeleteAsync(element.Id).Wait();
return true;
}
catch
{
return false;
}
}
public Form GetForm(PluginsConventionElement? element = null)
=> new CreateForm(_studentRepository, _educationFormRepository, element?.Id);
public Form GetThesaurus()
=> new CatalogForm(_educationFormRepository);
public async void ReloadData()
{
try
{
var students = _mapper.Map<List<StudentViewModel>>(await _studentRepository.GetAsync());
_control.FillValues(
students.Select(s => string.Join(" ",
[
s.Id,
s.Name,
s.EducationForm,
s.StartEducation.ToLongDateString(),
s.SessionMarks,
]
))
);
}
catch
{
}
}
static IServiceProvider CreateServiceProvider()
{
var builder = Host.CreateDefaultBuilder()
.ConfigureAppConfiguration(c
=> c.AddJsonFile("appsettings.plugins.json", optional: true, reloadOnChange: true))
.ConfigureServices((context, services) => {
services.ConfigureDAL(context.Configuration);
services.AddMapping();
services.AddLab3Forms();
});
return builder.Build().Services;
}
}
}

View File

@ -1,13 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Lab3\Lab3.csproj" />
<ProjectReference Include="..\Lab4\Lab4.csproj" />
</ItemGroup>
</Project>

View File

@ -1,7 +0,0 @@
namespace Lab4
{
public record PluginsConfigurations
{
public string FolderPath { get; set; } = string.Empty;
}
}

View File

@ -1,16 +0,0 @@
using Lab4.Forms;
using Microsoft.Extensions.DependencyInjection;
namespace Lab4.Extensions
{
public static class DiExtensions
{
public static IServiceCollection AddForms(
this IServiceCollection services)
{
services.AddScoped<FormMain>();
return services;
}
}
}

View File

@ -1,188 +0,0 @@
using System.ComponentModel;
namespace Lab4.Forms
{
partial class FormMain
{
/// <summary>
/// Required designer variable.
/// </summary>
private IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.menuStrip = new MenuStrip();
this.ControlsStripMenuItem = new ToolStripMenuItem();
this.ActionsToolStripMenuItem = new ToolStripMenuItem();
this.DocsToolStripMenuItem = new ToolStripMenuItem();
this.SimpleDocToolStripMenuItem = new ToolStripMenuItem();
this.TableDocToolStripMenuItem = new ToolStripMenuItem();
this.ChartDocToolStripMenuItem = new ToolStripMenuItem();
this.panelControl = new Panel();
this.ThesaurusToolStripMenuItem = new ToolStripMenuItem();
this.AddElementToolStripMenuItem = new ToolStripMenuItem();
this.UpdElementToolStripMenuItem = new ToolStripMenuItem();
this.DelElementToolStripMenuItem = new ToolStripMenuItem();
this.menuStrip.SuspendLayout();
this.SuspendLayout();
//
// menuStrip
//
this.menuStrip.Items.AddRange(new ToolStripItem[] {
this.ControlsStripMenuItem,
this.ActionsToolStripMenuItem,
this.DocsToolStripMenuItem});
this.menuStrip.Location = new Point(0, 0);
this.menuStrip.Name = "menuStrip";
this.menuStrip.Size = new Size(800, 24);
this.menuStrip.TabIndex = 0;
this.menuStrip.Text = "Меню";
//
// ControlsStripMenuItem
//
this.ControlsStripMenuItem.Name = "ControlsStripMenuItem";
this.ControlsStripMenuItem.Size = new Size(94, 20);
this.ControlsStripMenuItem.Text = "Компоненты";
//
// ActionsToolStripMenuItem
//
this.ActionsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] {
this.ThesaurusToolStripMenuItem,
this.AddElementToolStripMenuItem,
this.UpdElementToolStripMenuItem,
this.DelElementToolStripMenuItem});
this.ActionsToolStripMenuItem.Name = "ActionsToolStripMenuItem";
this.ActionsToolStripMenuItem.Size = new Size(70, 20);
this.ActionsToolStripMenuItem.Text = "Действия";
//
// DocsToolStripMenuItem
//
this.DocsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] {
this.SimpleDocToolStripMenuItem,
this.TableDocToolStripMenuItem,
this.ChartDocToolStripMenuItem});
this.DocsToolStripMenuItem.Name = "DocsToolStripMenuItem";
this.DocsToolStripMenuItem.Size = new Size(82, 20);
this.DocsToolStripMenuItem.Text = "Документы";
//
// SimpleDocToolStripMenuItem
//
this.SimpleDocToolStripMenuItem.Name = "SimpleDocToolStripMenuItem";
this.SimpleDocToolStripMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.S)));
this.SimpleDocToolStripMenuItem.Size = new Size(233, 22);
this.SimpleDocToolStripMenuItem.Text = "Простой документ";
this.SimpleDocToolStripMenuItem.Click += new EventHandler(this.SimpleDocToolStripMenuItem_Click);
//
// TableDocToolStripMenuItem
//
this.TableDocToolStripMenuItem.Name = "TableDocToolStripMenuItem";
this.TableDocToolStripMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.T)));
this.TableDocToolStripMenuItem.Size = new Size(233, 22);
this.TableDocToolStripMenuItem.Text = "Документ с таблицей";
this.TableDocToolStripMenuItem.Click += new EventHandler(this.TableDocToolStripMenuItem_Click);
//
// ChartDocToolStripMenuItem
//
this.ChartDocToolStripMenuItem.Name = "ChartDocToolStripMenuItem";
this.ChartDocToolStripMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.C)));
this.ChartDocToolStripMenuItem.Size = new Size(233, 22);
this.ChartDocToolStripMenuItem.Text = "Диаграмма";
this.ChartDocToolStripMenuItem.Click += new EventHandler(this.ChartDocToolStripMenuItem_Click);
//
// panelControl
//
this.panelControl.Dock = DockStyle.Fill;
this.panelControl.Location = new Point(0, 24);
this.panelControl.Name = "panelControl";
this.panelControl.Size = new Size(800, 426);
this.panelControl.TabIndex = 1;
//
// ThesaurusToolStripMenuItem
//
this.ThesaurusToolStripMenuItem.Name = "ThesaurusToolStripMenuItem";
this.ThesaurusToolStripMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.I)));
this.ThesaurusToolStripMenuItem.Size = new Size(180, 22);
this.ThesaurusToolStripMenuItem.Text = "Справочник";
this.ThesaurusToolStripMenuItem.Click += new EventHandler(this.ThesaurusToolStripMenuItem_Click);
//
// AddElementToolStripMenuItem
//
this.AddElementToolStripMenuItem.Name = "AddElementToolStripMenuItem";
this.AddElementToolStripMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.A)));
this.AddElementToolStripMenuItem.Size = new Size(180, 22);
this.AddElementToolStripMenuItem.Text = "Добавить";
this.AddElementToolStripMenuItem.Click += new EventHandler(this.AddElementToolStripMenuItem_Click);
//
// UpdElementToolStripMenuItem
//
this.UpdElementToolStripMenuItem.Name = "UpdElementToolStripMenuItem";
this.UpdElementToolStripMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.U)));
this.UpdElementToolStripMenuItem.Size = new Size(180, 22);
this.UpdElementToolStripMenuItem.Text = "Изменить";
this.UpdElementToolStripMenuItem.Click += new EventHandler(this.UpdElementToolStripMenuItem_Click);
//
// DelElementToolStripMenuItem
//
this.DelElementToolStripMenuItem.Name = "DelElementToolStripMenuItem";
this.DelElementToolStripMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.D)));
this.DelElementToolStripMenuItem.Size = new Size(180, 22);
this.DelElementToolStripMenuItem.Text = "Удалить";
this.DelElementToolStripMenuItem.Click += new EventHandler(this.DelElementToolStripMenuItem_Click);
//
// FormMain
//
this.AutoScaleDimensions = new SizeF(7F, 15F);
this.AutoScaleMode = AutoScaleMode.Font;
this.ClientSize = new Size(800, 450);
this.Controls.Add(this.panelControl);
this.Controls.Add(this.menuStrip);
this.MainMenuStrip = this.menuStrip;
this.Name = "FormMain";
this.StartPosition =
FormStartPosition.CenterScreen;
this.Text = "Главная форма";
this.WindowState =
FormWindowState.Maximized;
this.KeyDown += new
KeyEventHandler(this.FormMain_KeyDown);
this.menuStrip.ResumeLayout(false);
this.menuStrip.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private MenuStrip menuStrip;
private ToolStripMenuItem ControlsStripMenuItem;
private ToolStripMenuItem DocsToolStripMenuItem;
private ToolStripMenuItem SimpleDocToolStripMenuItem;
private ToolStripMenuItem TableDocToolStripMenuItem;
private ToolStripMenuItem ChartDocToolStripMenuItem;
private Panel panelControl;
private ToolStripMenuItem ActionsToolStripMenuItem;
private ToolStripMenuItem ThesaurusToolStripMenuItem;
private ToolStripMenuItem AddElementToolStripMenuItem;
private ToolStripMenuItem UpdElementToolStripMenuItem;
private ToolStripMenuItem DelElementToolStripMenuItem;
}
}

View File

@ -1,261 +0,0 @@
using Lab4.Interfaces;
using Lab4.Plugins.Models;
using Microsoft.Extensions.Options;
using System.Reflection;
namespace Lab4.Forms
{
public partial class FormMain : Form
{
private readonly Dictionary<string, IPluginsConvention> _plugins;
private readonly PluginsConfigurations _pluginsConfigurations;
private string _selectedPlugin = string.Empty;
public FormMain(IOptions<PluginsConfigurations> pluginsConfigs)
{
InitializeComponent();
_pluginsConfigurations = pluginsConfigs.Value;
_plugins = LoadPlugins();
}
private Dictionary<string, IPluginsConvention> LoadPlugins()
{
Dictionary<string, IPluginsConvention> result = [];
var plurinInterface = typeof(IPluginsConvention);
foreach (var type in Directory
.GetFiles(_pluginsConfigurations.FolderPath, "*.dll", SearchOption.AllDirectories)
.Select(Assembly.LoadFrom)
.SelectMany(x => x.GetTypes())
.Where(x => plurinInterface.IsAssignableFrom(x) && !x.IsInterface))
{
var plugin = type.GetConstructor([])?.Invoke([]);
if (plugin == null)
{
continue;
}
IPluginsConvention pluginObject = (plugin as IPluginsConvention)!;
string key = pluginObject.PluginName;
result[key] = pluginObject;
var item = new ToolStripMenuItem(key);
item.Click += (s, e) =>
{
_selectedPlugin = key;
panelControl.Controls.Clear();
_plugins[_selectedPlugin].ReloadData();
var control = _plugins[key].GetControl;
control.Parent = panelControl;
control.Dock = DockStyle.Fill;
panelControl.Controls.Add(control);
};
ControlsStripMenuItem.DropDownItems!.Add(item);
}
return result;
}
private void FormMain_KeyDown(object sender, KeyEventArgs e)
{
if (string.IsNullOrEmpty(_selectedPlugin) || !_plugins.ContainsKey(_selectedPlugin))
{
return;
}
if (!e.Control)
{
return;
}
switch (e.KeyCode)
{
case Keys.I:
ShowThesaurus();
break;
case Keys.A:
AddNewElement();
break;
case Keys.U:
UpdateElement();
break;
case Keys.D:
DeleteElement();
break;
case Keys.S:
CreateSimpleDoc();
break;
case Keys.T:
CreateTableDoc();
break;
case Keys.C:
CreateChartDoc();
break;
}
}
private void ShowThesaurus()
{
_plugins[_selectedPlugin].GetThesaurus()?.Show();
}
private void AddNewElement()
{
var form = _plugins[_selectedPlugin].GetForm();
if (form != null && form.ShowDialog() == DialogResult.OK)
{
_plugins[_selectedPlugin].ReloadData();
}
}
private void UpdateElement()
{
var element = _plugins[_selectedPlugin].GetElement;
if (element == null)
{
_ = MessageBox.Show("Нет выбранного элемента", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var form = _plugins[_selectedPlugin].GetForm(element);
if (form != null && form.ShowDialog() == DialogResult.OK)
{
_plugins[_selectedPlugin].ReloadData();
}
}
private void DeleteElement()
{
if (MessageBox.Show("Удалить выбранный элемент", "Удаление",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
{
return;
}
var element = _plugins[_selectedPlugin].GetElement;
if (element == null)
{
_ = MessageBox.Show("Нет выбранного элемента", "Ошибка",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (_plugins[_selectedPlugin].DeleteElement(element))
{
_plugins[_selectedPlugin].ReloadData();
}
}
private void CreateSimpleDoc()
{
using var saveFileDialog = new SaveFileDialog
{
Filter = "pdf|*.pdf"
};
if (saveFileDialog.ShowDialog() != DialogResult.OK)
{
return;
}
if (_plugins[_selectedPlugin].CreateSimpleDocument(new PluginsConventionSaveDocument()
{
FileName = saveFileDialog.FileName,
}))
{
_ = MessageBox.Show("Документ сохранен",
"Создание документа",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
_ = MessageBox.Show("Ошибка при создании документа", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void CreateTableDoc()
{
using var saveFileDialog = new SaveFileDialog
{
Filter = "xlsx|*.xlsx"
};
if (saveFileDialog.ShowDialog() != DialogResult.OK)
{
return;
}
if (_plugins[_selectedPlugin].CreateTableDocument(new
PluginsConventionSaveDocument()
{
FileName = saveFileDialog.FileName,
}))
{
_ = MessageBox.Show("Документ сохранен",
"Создание документа",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
_ = MessageBox.Show("Ошибка при создании документа", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void CreateChartDoc()
{
using var saveFileDialog = new SaveFileDialog
{
Filter = "docx|*.docx"
};
if (saveFileDialog.ShowDialog() != DialogResult.OK)
{
return;
}
if (_plugins[_selectedPlugin].CreateChartDocument(new PluginsConventionSaveDocument()
{
FileName = saveFileDialog.FileName,
}))
{
_ = MessageBox.Show("Документ сохранен",
"Создание документа",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
_ = MessageBox.Show("Ошибка при создании документа", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ThesaurusToolStripMenuItem_Click(object sender, EventArgs e) => ShowThesaurus();
private void AddElementToolStripMenuItem_Click(object sender, EventArgs e) => AddNewElement();
private void UpdElementToolStripMenuItem_Click(object sender, EventArgs e) => UpdateElement();
private void DelElementToolStripMenuItem_Click(object sender, EventArgs e) => DeleteElement();
private void SimpleDocToolStripMenuItem_Click(object sender, EventArgs e) => CreateSimpleDoc();
private void TableDocToolStripMenuItem_Click(object sender, EventArgs e) => CreateTableDoc();
private void ChartDocToolStripMenuItem_Click(object sender, EventArgs e) => CreateChartDoc();
}
}

View File

@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,68 +0,0 @@
using Lab4.Plugins.Models;
namespace Lab4.Interfaces
{
public interface IPluginsConvention
{
/// <summary>
/// Название плагина
/// </summary>
string PluginName { get; }
/// <summary>
/// Получение контрола для вывода набора данных
/// </summary>
UserControl GetControl { get; }
/// <summary>
/// Получение элемента, выбранного в контроле
/// </summary>
PluginsConventionElement GetElement { get; }
/// <summary>
/// Получение формы для создания/редактирования объекта
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
Form GetForm(PluginsConventionElement? element = null);
/// <summary>
/// Получение формы для работы со справочником
/// </summary>
/// <returns></returns>
Form GetThesaurus();
/// <summary>
/// Удаление элемента
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
bool DeleteElement(PluginsConventionElement element);
/// <summary>
/// Обновление набора данных в контроле
/// </summary>
void ReloadData();
/// <summary>
/// Создание простого документа
/// </summary>
/// <param name="saveDocument"></param>
/// <returns></returns>
bool CreateSimpleDocument(PluginsConventionSaveDocument saveDocument);
/// <summary>
/// Создание простого документа
/// </summary>
/// <param name="saveDocument"></param>
/// <returns></returns>
bool CreateTableDocument(PluginsConventionSaveDocument saveDocument);
/// <summary>
/// Создание документа с диаграммой
/// </summary>
/// <param name="saveDocument"></param>
/// <returns></returns>
bool CreateChartDocument(PluginsConventionSaveDocument saveDocument);
}
}

View File

@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -1,7 +0,0 @@
namespace Lab4.Plugins.Models
{
public class PluginsConventionElement
{
public Guid Id { get; set; }
}
}

View File

@ -1,7 +0,0 @@
namespace Lab4.Plugins.Models
{
public class PluginsConventionSaveDocument
{
public string FileName { get; set; } = null!;
}
}

View File

@ -1,38 +0,0 @@
using Lab4.Extensions;
using Lab4.Forms;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Lab4
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
var app = CreateHostBuilder().Build();
Application.Run(app.Services.GetRequiredService<FormMain>());
}
static IHostBuilder CreateHostBuilder()
{
return Host.CreateDefaultBuilder()
.ConfigureAppConfiguration(c
=> c.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true))
.ConfigureServices((context, services) => {
services.AddForms();
services.Configure<PluginsConfigurations>(
context.Configuration.GetSection(nameof(PluginsConfigurations)));
});
}
}
}

View File

@ -1,8 +0,0 @@
{
"PluginsConfigurations": {
"FolderPath": "C:\\data\\Plugins"
},
"ConnectionStrings": {
"COPDataBase": "Host=localhost;Username=postgres;Password=postgres;Database=COP"
}
}

View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>Библиотека PDF</Title>
<Authors>MaximK</Authors>
<Description>Небольшая надстройка для более удобной работы с PDF</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/KuzarinM/PIHelperSh/tree/master/PIHelperSh.PdfCreater</RepositoryUrl>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<Version>1.1.1</Version>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
<PackageReference Include="PIHelperSh.Core" Version="1.0.1" />
</ItemGroup>
</Project>

View File

@ -1,59 +0,0 @@
namespace TestCustomComponents.Forms
{
partial class Form3
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
button1 = new Button();
SuspendLayout();
//
// button1
//
button1.Location = new Point(103, 83);
button1.Name = "button1";
button1.Size = new Size(94, 29);
button1.TabIndex = 0;
button1.Text = "button1";
button1.UseVisualStyleBackColor = true;
button1.Click += button1_Click;
//
// Form3
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 450);
Controls.Add(button1);
Name = "Form3";
Text = "Form3";
ResumeLayout(false);
}
#endregion
private Button button1;
}
}

View File

@ -1,28 +0,0 @@
using Lab4.Plugins.Implementations;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestCustomComponents.Forms
{
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var test = new PluginsConvention();
int a = 1;
}
}
}

View File

@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -4,7 +4,7 @@
{ {
public int Id { get; set; } public int Id { get; set; }
public string Name { get; set; } public string Name { get; set; } = string.Empty;
public int Age { get; set; } public int Age { get; set; }

View File

@ -13,7 +13,7 @@ namespace TestCustomComponents
// To customize application configuration such as set high DPI settings or default font, // To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration. // see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize(); ApplicationConfiguration.Initialize();
Application.Run(new Form3()); Application.Run(new Form2());
} }
} }
} }

View File

@ -9,7 +9,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Lab4.Plugins\Lab4.Plugins.csproj" /> <ProjectReference Include="..\Cop.Borovkov.Var3\Cop.Borovkov.Var3.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,94 +0,0 @@
# Лабораторная работа №5.
# Применение структурных паттернов.
## Задание
1) Дать описание паттернов, указанных во вариантах, для каких целей они могут применяться,
какие участники там фигурируют.
2) На основе задания из 3 лабораторной работы, для каждого паттерна придумать сущности,
относящиеся к той же предметной области, что описаны в задании и реализация которых
бы в приложении потребовала применения паттерна.
### Ограничения:
- На каждый паттерн свои сущности
- В качестве источника сущностей использовать предметную область задания 3 лабораторной работы, а не элементы разработки (что-то типа «У меня паттерн Singleton, укажу ка я класс-подключение к БД через него», не принимается).
3) Создать диаграммы классов, отражающие взаимодействие новых
сущностей (а также используемый паттерн) с классами,
созданными в рамках 3 лабораторной работы. Отдельно отметить
классы, которые являются участниками паттерна
## Вариант 3: _Adapter, Composite, Proxy_
### Паттерн Adapter
Паттерн Адаптер используется для того,
чтобы объекты с несовместимыми интерфейсами могли работать вместе.
Он оборачивает один интерфейс в другой,
делая несовместимые классы совместимыми без изменения их исходного кода.
Задачи, которые решает паттерн Adapter:
- Интеграция стороннего кода или библиотек:
когда требуется использовать стороннюю библиотеку с вашим приложением,
но её интерфейс отличается от имеющегося интерфейса.
- Обратная совместимость: когда нужно подключить новый код к старому интерфейсу, не изменяя существующий.
- Упрощение взаимодействия: уменьшает сложность работы с несколькими несовместимыми компонентами.
Участники:
- Target: представляет объекты, которые используются клиентом.
- Client: использует объекты Target для реализации своих задач.
- Adaptee: представляет адаптируемый класс, который хотелось бы использовать у клиента вместо объектов Target.
- Adapter: сам адаптер, который позволяет работать с объектами Adaptee как с объектами Target.
**Пример реализации для рассматриваемой предметной области:**<br>
Классы, реализующие паттерн:
- IStudentTracker (Target) Интерфейс системы отслеживания успеваемости студентов
- StudentManager (Client) Использует данные о успеваемости, для определеня судьбы студентов
- AttendanceTracker (Adaptee) Реализализовывает систему отслеживания посещаемости студентов
- StudentTrackerAdapter (Adapter) "оборачивает" стороннюю систему и преобразует её в интерфейс, ожидаемый клиентом
![img_3.png](img_3.png)
### Паттерн Composite
Паттерн Компоновщик (Composite) объединяет группы объектов в древовидную структуру
по принципу "часть-целое и позволяет клиенту одинаково работать как с отдельными объектами,
так и с группой объектов.
Образно реализацию паттерна можно представить в виде меню,
которое имеет различные пункты. Эти пункты могут содержать подменю, в которых,
в свою очередь, также имеются пункты. То есть пункт меню служит с одной стороны частью меню,
а с другой стороны еще одним меню. В итоге мы однообразно можем работать как с пунктом меню,
так и со всем меню в целом.
Участники:
- Component определяет интерфейс для всех компонентов в древовидной структуре
- Composite представляет компонент, который может содержать другие компоненты
и реализует механизм для их добавления и удаления
- Leaf представляет отдельный компонент, который не может содержать другие компоненты
- Client клиент, который использует компоненты
Классы, реализующие паттерн:
- IStudent (Component) Студент обучающийся в вузе
- Group (Composite) Группировка студентов (групаа в потоке, поток, курс...)
- Student (Leaf) Конкретный студент
- University (Client) Обеспечивает обучение студентов
![img.png](img.png)
### Паттерн Proxy
Паттерн Заместитель (Proxy) предоставляет объект-заместитель, который управляет доступом к другому объекту.
То есть создается объект-суррогат, который может выступать в роли другого объекта и замещать его.
Участники:
- Subject определяет общий интерфейс для Proxy и RealSubject. Поэтому Proxy может использоваться вместо RealSubject
- RealSubject представляет реальный объект, для которого создается прокси
- Proxy заместитель реального объекта. Хранит ссылку на реальный объект, контролирует к нему доступ,
может управлять его созданием и удалением. При необходимости Proxy переадресует запросы объекту RealSubject
- Client использует объект Proxy для доступа к объекту RealSubject
Классы, реализующие паттерн:
- IStudent (Subject) Студент
- Student (RealSubject) Студент из группы
- Elder (Proxy) Староста отвечает на вопросы преподователя, при надомности спрашивает студентов группы
- Lecturer (Client) - Задаёт вопросы студентам через старосту
![img_2.png](img_2.png)

View File

@ -1,92 +0,0 @@
# Лабораторная работа №6.
# Применение структурных паттернов.
## Задание
1) Дать описание паттернов, указанных во вариантах, для каких целей они могут применяться,
какие участники там фигурируют.
2) На основе задания из 3 лабораторной работы, для каждого паттерна придумать сущности,
относящиеся к той же предметной области, что описаны в задании и реализация которых
бы в приложении потребовала применения паттерна.
### Ограничения
- На каждый паттерн свои сущности
- В качестве источника сущностей использовать предметную область задания 3 лабораторной работы,
а не элементы разработки (что-то типа «У меня паттерн Singleton,
укажу ка я класс-подключение к БД через него», не принимается).
3) Создать диаграммы классов, отражающие взаимодействие новых
сущностей (а также используемый паттерн) с классами,
созданными в рамках 3 лабораторной работы. Отдельно отметить
классы, которые являются участниками паттерна
## Вариант 3 _AbstractFactory, FactoryMethod, ObjectPool._
### Паттерн AbstractFactory
Паттерн "Абстрактная фабрика" (Abstract Factory) предоставляет интерфейс для создания семейств
взаимосвязанных объектов с определенными интерфейсами без указания конкретных типов данных объектов.
Участники
- AbstractProductA и AbstractProductB абстрактные классы, определяющие интерфейс для классов,
объекты которых будут создаваться в программе
- ProductA1 / ProductA2 и ProductB1 / ProductB2 конкретные классы,
представляющие конкретную реализацию абстрактных классов.
- AbstractFactory - Абстрактный класс фабрики определяет методы для создания объектов.
Причем методы возвращают абстрактные продукты, а не их конкретные реализации.
- Client класс клиента, использующий класс фабрики для создания объектов.
При этом он использует исключительно абстрактный класс фабрики AbstractFactory
и абстрактные классы продуктов AbstractProductA и AbstractProductB и никак не зависит от их конкретных реализаций.
Классы, реализующие паттерн:
- IReportFactory (Abstract Factory) интерфейс фабрики для создания отчетов.
- FivePointReportFactory (Concrete Factory) фабрика для 5-балльной системы.
- HundredPointReportFactory (Concrete Factory) фабрика для 100-балльной системы.
- IPerformanceReport (Abstract Product) интерфейс для отчета по успеваемости.
- FivePointPerformanceReport и HundredPointPerformanceReport (Concrete Products) конкретные реализации отчетов по успеваемости для 5- и 10-балльной систем.
- ILaggingStudentsReport (Abstract Product) интерфейс для отчета по отстающим студентам.
- FivePointLaggingStudentsReport и HundredPointLaggingStudentsReport (Concrete Products) отчеты по отстающим студентам для 5- и 10-балльной систем.
- ReportManager (Client) класс, который обрабатывает отчеты
![img_4.png](img_4.png)
### Паттерн FactoryMethod
Фабричный метод (Factory Method) - это паттерн, который определяет интерфейс для создания объектов некоторого класса,
но непосредственное решение о том, объект какого класса создавать происходит в подклассах.
То есть паттерн предполагает, что базовый класс делегирует создание объектов классам-наследникам.
Участники:
- Product интерфейс или абстрактный класс, определяющий структуру создаваемых объектов.
- ConcreteProductA и ConcreteProductB конкретные реализации интерфейса “Product”, представляющие первый и второй тип продукта.
- Creator абстрактный класс или интерфейс, который определяет фабричный метод для создания объектов типа “Product”.
- ConcreteCreatorA и ConcreteCreatorB конкретные реализации “Creator”, которая создаёт объекты типа “ConcreteProductA” и “ConcreteCreatorB” соответственно.
Классы, реализующие паттерн:
- Product IReport определяет интерфейс для всех отчетов.
- ConcreteProductA и ConcreteProductB GradeReport и AttendanceReport конкретные реализации интерфейса “IReport”.
- Creator ReportCreator определяет фабричный метод для создания объектов типа “IReport”.
- ConcreteCreatorA и ConcreteCreatorB GradeReportCreator и AttendanceReportCreator конкретные реализации “ReportCreator”.
![img_5.png](img_5.png)
### Паттерн ObjectPool
Object Pool (пул объектов) — это поведенческий паттерн, который используется для оптимизации управления ресурсами.
Он позволяет многократно использовать уже созданные объекты вместо их повторного создания и уничтожения.
Это особенно полезно, когда создание объектов является дорогой операцией с точки зрения времени или ресурсов.
Участники:
- Pool управляет коллекцией объектов. Отвечает за выдачу и возврат объектов из пула. Решает, когда создавать новый объект или использовать существующий.
- ReusableObject (повторно используемый объект) - объект, который находится в пуле и может быть многократно использован. Включает логику и состояние объекта.
- Client - получает объект из пула для использования. Возвращает объект обратно в пул, когда он больше не нужен.
Классы, реализующие паттерн:
- Pool FormatPool управляет доступностью объектов “Format”. Позволяет выдавать объекты формы обучения для студентов.
- ReusableObject Format содержит данные, связанные с конкретной формой обучения.
- Client Student представляет студента и содержит данные о нем.
![img_6.png](img_6.png)

View File

@ -1,74 +0,0 @@
# Лабораторная работа №7.
# Применение структурных паттернов.
## Задание
1) Дать описание паттернов, указанных во вариантах, для каких целей они могут применяться,
какие участники там фигурируют.
2) На основе задания из 3 лабораторной работы, для каждого паттерна придумать сущности,
относящиеся к той же предметной области, что описаны в задании и реализация которых
бы в приложении потребовала применения паттерна.
### Ограничения
- На каждый паттерн свои сущности
- В качестве источника сущностей использовать предметную область задания 3 лабораторной работы,
а не элементы разработки (что-то типа «У меня паттерн Singleton,
укажу ка я класс-подключение к БД через него», не принимается).
3) Создать диаграммы классов, отражающие взаимодействие новых
сущностей (а также используемый паттерн) с классами,
созданными в рамках 3 лабораторной работы. Отдельно отметить
классы, которые являются участниками паттерна
## Вариант 3 _Mediator, Mediator (2 различных реализации), Strategy._
### Паттерн Mediator
Паттерн "Посредник" (Mediator) представляет такой шаблон проектирования,
который обеспечивает взаимодействие множества объектов без необходимости ссылаться друг на друга.
Тем самым достигается слабосвязанность взаимодействующих объектов.
Участники
- Mediator - представляет интерфейс для взаимодействия с объектами Colleague.
- Colleague - представляет интерфейс для взаимодействия с объектом Mediator.
- ConcreteColleague1 и ConcreteColleague2 - конкретные классы коллег,
которые обмениваются друг с другом через объект Mediator.
- ConcreteMediator - конкретный посредник, реализующий интерфейс типа Mediator.
Классы, реализующие паттерн:
- Secretary Mediator - Секретарь
- Client Colleague - Участник вузовской системы
- Teacher ConcreteColleague1 - Преподователь
- Student ConcreteColleague2 - Студент
- Dean`s Office ConcreteMediator - Деканат
![img_8.png](img_8.png)
- ILms Mediator - Сайт лмс
- User Colleague - Пользователь лмс
- Teacher ConcreteColleague1 - Преподователь
- Student ConcreteColleague2 - Студент
- Lms ConcreteMediator - Логика сайта лмс
![img_7.png](img_7.png)
### Паттерн Strategy
Strategy (Стратегия) — шаблон проектирования, который определяет набор алгоритмов, инкапсулирует каждый из них
и обеспечивает их взаимозаменяемость.
В зависимости от ситуации мы можем легко заменить один используемый алгоритм другим.
При этом замена алгоритма происходит независимо от объекта, который использует данный алгоритм.
Участники:
- IStrategy: интерфейс, который определяет метод Algorithm(). Это общий интерфейс для всех реализующих его алгоритмов.
Вместо интерфейса здесь также можно было бы использовать абстрактный класс.
- ConcreteStrategy1 и ConcreteStrategy2: классы, которые реализуют интерфейс IStrategy,
предоставляя свою версию метода Algorithm(). Подобных классов-реализаций может быть множество.
- Context: класс, который хранит ссылку на объект IStrategy и связан с интерфейсом IStrategy отношением агрегации.
Классы, реализующие паттерн:
- IStrategy IStudentWorkChecker общий интерфейс для всех стратегий проверку индивидуальной работы студента.
- СourseWorkChecker, LabWorkChecker - классы, реализующие проверку ирс
- Context Teacher Преподаватель выбирает подходящцю стратегию для проверки работы
![img_10.png](img_10.png)

View File

@ -1,144 +1,109 @@
# Лабораторная работа 1 # Лабораторная работа 1
## Компоненты: ## Компоненты:
### CustomDataTable:
Визуальный компонент вывода таблицы значений
__Публичные Методы__:
- Определить структуру таблицы
```c#
void ConfigureColumns(params CustomDataTableColumnParameter[] columnParameters)
```
CustomDataTableColumnParameter
```c#
/// <summary>
/// Параметры столбца таблицы
/// </summary>
public record CustomDataTableColumnParameter
{
/// <summary>
/// Заголовок
/// </summary>
public string HeaderName { get; init; } = string.Empty;
/// <summary>
/// Ширина
/// </summary>
public int Width { get; init; } = 0;
/// <summary>
/// Видимость
/// </summary>
public bool Visible { get; init; } = true;
/// <summary>
/// Название свойства
/// </summary>
public string PropertyName { get; init; } = string.Empty;
}
```
- Отчистить таблицу
```c#
public void Clear()
```
- Заполнить таблицу
```c#
public void Fill<TType>(IList<TType> insertValues)
```
__Публичные Функции__:
- Получить стоку таблицы в виде объекта
```c#
public TType? GetRow<TType>(int rowIndex) where TType : new()
```
__Свойства__:
- Индекс выбранной строки
```c#
public int SelectedRow
```
### CustomListBox ### CustomListBox
Визуальный компонент выбора из списка значений
Пользовательский визуальный компонент, который наследуется от UserControl. __Публичные Методы__:
Этот компонент является оберткой вокруг стандартного ListBox и предоставляет функционал для выбора значений из списка. - Заполнить список значениями
Класс поддерживает заполнение списка значениями, очистку списка, ```c#
обработку выбора элемента и уведомление об ошибках. public void FillValues(IEnumerable<string> strings)
```
- Очистить список
```c#
public void Clear()
```
--- __Свойства__:
- Событие возникающие при изменении списка
### Свойства: ```c#
public event EventHandler ValueChanged
1. Selected (тип: `string`) ```
- Функция: Возвращает или устанавливает выбранное значение в списке. - Обработка ошибок
- get: Возвращает выбранный элемент списка или пустую строку, если элемент не выбран. ```c#
- set: Устанавливает выбранный элемент списка, если он существует. public event Action<Exception> AnErrorOccurred
```
--- - Выбранное значение
```c#
### Методы: public string Selected
```
1. FillValues(IEnumerable<string> strings)
- Функция: Заполняет список значениями из переданной коллекции строк.
2. Clear()
- Функция: Очищает список, сбрасывает выбор и обновляет отображение.
---
### Поля:
1. _selectedChanged (тип: `EventHandler?`)
- Функция: Хранит подписчиков на событие изменения выбранного элемента.
2. _errorOccured (тип: `Action<Exception>?`)
- Функция: Хранит подписчиков на событие возникновения ошибки.
---
### События:
1. ValueChanged (тип: `EventHandler`)
- Функция: Событие, возникающее при изменении выбранного элемента в списке.
2. AnErrorOccurred (тип: `Action<Exception>`)
- Функция: Событие, возникающее при возникновении ошибки в процессе обработки выбранного элемента.
### CustomDataTable
CustomDataTable представляет собой пользовательский визуальный компонент, который наследуется от UserControl.
Этот компонент является оберткой вокруг стандартного DataGridView
и предоставляет функционал для отображения и управления таблицей данных. Класс поддерживает настройку столбцов,
заполнение таблицы данными, очистку таблицы, выбор строки и получение данных из строки в виде объекта.
---
### Свойства:
1. SelectedRow (тип: `int`)
- Функция: Возвращает или устанавливает индекс выбранной строки в таблице.
- get: Возвращает индекс текущей выбранной строки.
- set: Устанавливает выбранную строку по индексу.
---
### Методы:
1. ConfigureColumns(params CustomDataTableColumnParameter[] columnParameters)
- Функция: Настраивает столбцы таблицы на основе переданных параметров.
2. Clear()
- Функция: Очищает таблицу, удаляя все строки.
3. GetRow<TType>(int rowIndex)
- Функция: Возвращает данные из указанной строки таблицы в виде объекта типа TType.
4. Fill<TType>(IList<TType> insertValues)
- Функция: Заполняет таблицу данными из переданного списка объектов.
---
### Поля:
- outDataGridView (тип: `DataGridView`)
- Функция: Внутренний элемент управления DataGridView, используемый для отображения таблицы.
---
### CustomNumericInputField ### CustomNumericInputField
Визуальный компонент ввода целочисленного значения допускающего null
CustomNumericInputField представляет собой пользовательский визуальный компонент, __Свойства__:
который наследуется от UserControl. - Событие возникающие при изменении поля ввода
Этот компонент предназначен для ввода целочисленных значений, которые могут быть null. ```c#
Он включает текстовое поле для ввода числа и флажок (чекбокс) для указания, public event EventHandler NumericInputChanged
что значение должно быть null. Компонент также поддерживает события для обработки изменений ввода и ошибок. ```
- Обработка ошибок
--- ```c#
public event Action<Exception> AnErrorOccurred
### Свойства: ```
- Значения поля ввода
1. Value (тип: `int?`) ```c#
- Функция: Возвращает или устанавливает значение поля ввода. public int? Value
- get: Возвращает введенное целое число или null, если флажок "null" активен. ```
Если введенное значение не является числом, выбрасывает исключение InvalidNumericInputValueException. _Возможно исключение ```InvalidNumericInputValueException```_
- set: Устанавливает значение поля ввода. Если значение null, активирует флажок "null" и очищает текстовое поле.
---
### Методы:
1. Приватный: IsNullcheckBox_CheckedChanged(object sender, EventArgs e)
- Функция: Обрабатывает изменение состояния флажка "null". Если флажок активен,
отключает текстовое поле и очищает его. Вызывает событие _numericInputChanged или _errorOccurred в случае ошибки.
2. Приватный: InputField_TextChanged(object sender, EventArgs e)
- Функция: Обрабатывает изменение текста в поле ввода.
Вызывает событие _numericInputChanged или _errorOccurred в случае ошибки.
---
### Поля:
1. _numericInputChanged (тип: `EventHandler?`)
- Функция: Хранит подписчиков на событие изменения значения в поле ввода.
2. _errorOccured (тип: `Action<Exception>?`)
- Функция: Хранит подписчиков на событие возникновения ошибки.
---
### События:
1. NumericInputChanged (тип: `EventHandler`)
- Функция: Событие, возникающее при изменении значения в поле ввода (включая активацию флажка "null").
2. AnErrorOccurred (тип: `Action<Exception>`)
- Функция: Событие, возникающее при возникновении ошибки в процессе обработки ввода.
---
# Лабораторная работа 2 # Лабораторная работа 2
@ -146,391 +111,117 @@ CustomNumericInputField представляет собой пользовате
### CustomPdfTable ### CustomPdfTable
Класс CustomPdfTable представляет собой компонент, который сохраняет данные в виде таблицы в PDF-документ. Компонент для сохранения таблицы в пдф
Этот компонент использует библиотеку PdfSharp.MigraDoc для создания и форматирования PDF-документов.
Класс поддерживает добавление заголовка документа,
создание таблиц на основе двумерных массивов строк и сохранение документа по указанному пути.
--- __Публичные Методы__:
- Определить структуру таблицы
```c#
public void SaveToPdf(PdfTableInfo tableInfo)
```
PdfTableInfo
```c#
/// <summary>
/// Параметры для создания таблиц в пдф
/// </summary>
public record PdfTableInfo
{
/// <summary>
/// имя файла (включая путь до файла)
/// </summary>
public string FilePath { get; init; } = @"C:\pdfTable.pdf";
### Методы: /// <summary>
/// название документа(заголовок в документе)
/// </summary>
public string Title { get; init; } = "Таблица";
1. SaveToPdf(PdfTableInfo tableInfo) /// <summary>
- Функция: Сохраняет данные в PDF-документ с таблицами. /// Список таблиц
- Параметры: /// </summary>
- tableInfo: Объект типа PdfTableInfo, public IEnumerable<string[,]> Tables { get; init; } = [];
- содержащий информацию о пути сохранения файла, заголовке документа и таблицах. }
- Логика: ```
- Проверяет, что таблицы не пусты.
- Создает PDF-документ с помощью PdfCreator.
- Добавляет заголовок документа.
- Для каждой таблицы создает строки и столбцы на основе двумерного массива строк.
- Сохраняет документ по указанному пути.
---
### CustomPdfTableWithGrouping ### CustomPdfTableWithGrouping
CustomPdfTableWithGrouping создает PDF-документ с таблицей, Компонент создающий таблицу и группирует элементы по 1 столбцу
группируя данные по первому столбцу. __Публичные Методы__:
Использует библиотеку PdfSharp.MigraDoc для создания и форматирования PDF-документов. - Сохранить в пдф
Класс поддерживает настройку заголовка таблицы, столбцов, строк и группировку данных. ```c#
public void SaveToPdf<TType>(PdfTableWithGroupingInfo<TType> tableInfo) where TType : class
```
PdfTableWithGroupingInfo
```c#
/// <summary>
/// Параметры для создания таблицы в пдф с группировкой по 1 столбцу
/// </summary>
public class PdfTableWithGroupingInfo<TType> where TType : class
{
/// <summary>
/// имя файла (включая путь до файла)
/// </summary>
public string FilePath { get; init; } = @"C:\pdfTable.pdf";
--- /// <summary>
/// название документа(заголовок в документе)
/// </summary>
public string Title { get; init; } = "Таблица";
### Методы: /// <summary>
/// Высота заголовков
/// </summary>
public float HeaderHeight { get; init; } = 0.5f;
1. SaveToPdf<TType>(PdfTableWithGroupingInfo<TType> tableInfo) /// <summary>
- Функция: Сохраняет данные в PDF-документ с таблицей, группируя строки по первому столбцу. /// Параметры столбцов
- Параметры: /// </summary>
- tableInfo: Объект типа PdfTableWithGroupingInfo<TType>, public IEnumerable<ColumnInfo> Columns { get; init; } = [];
содержащий информацию о пути сохранения файла, заголовке таблицы, столбцах и строках.
- Логика:
- Проверяет, что столбцы и строки не пусты.
- Создает PDF-документ с помощью PdfCreator.
- Добавляет заголовок таблицы в документ.
- Создает таблицу с указанными столбцами и строками, группируя данные по первому столбцу.
- Сохраняет документ по указанному пути.
---
/// <summary>
/// Список таблиц
/// </summary>
public IEnumerable<RowInfo<TType>> Rows { get; init; } = [];
}
```
### CustomPdfHistogram ### CustomPdfHistogram
CustomPdfHistogram представляет собой компонент, который сохраняет гистограмму в PDF-документ. Компонент создающий линейную диаграмму
Этот компонент использует библиотеку PdfSharp.MigraDoc для создания и форматирования PDF-документов. __Публичные Методы__:
Класс поддерживает добавление заголовка документа, - Сохранить гистограмму в пдф
создание гистограммы на основе переданных данных и сохранение документа по указанному пути. ```c#
public void SaveToPdf(PdfHistigramInfo histogramInfo)
--- ```
PdfHistigramInfo
### Методы: ```c#
/// <summary>
1. SaveToPdf(PdfHistigramInfo histogramInfo) /// Параметры для создания линейной диаграммы
- Функция: Сохраняет гистограмму в PDF-документ. /// </summary>
- Параметры: public record PdfHistigramInfo
- histogramInfo: Объект типа PdfHistigramInfo, содержащий информацию о пути сохранения файла, заголовке документа, {
заголовке диаграммы, данных и положении легенды. /// <summary>
- Логика: /// Имя файла (включая путь до файла)
- Проверяет корректность входных данных (путь к файлу, заголовки, данные). /// </summary>
- Создает PDF-документ с помощью PdfCreator. public string FilePath { get; init; } = @"C:\pdfTable.pdf";
- Добавляет заголовок документа.
- Создает линейную диаграмму на основе переданных данных.
- Сохраняет документ по указанному пути.
- Исключения:
- ArgumentException: Если входные данные некорректны (например, отсутствует путь к файлу, заголовок или данные).
---
# Лабораторная работа 3 /// <summary>
/// Заголовок документа
Программный продукт предназначен для учета успеваемости студентов и управления их данными. /// </summary>
Он позволяет хранить информацию о каждом студенте, public string DocumentTitle { get; init; } = "Гистограмма";
формировать отчеты в различных форматах (Word, PDF, Excel)
и визуализировать данные с помощью линейной диаграммы. /// <summary>
/// Заголовок диаграммы
### Цель программы /// </summary>
Цель программы — автоматизация процесса учета успеваемости студентов, public string HistogramTitle { get; init; } = "Гистограмма";
упрощение работы с данными и формирование отчетов для анализа успеваемости студентов.
/// <summary>
### Функционал программы /// Расположение легенды
- Хранение данных о студентах: /// </summary>
public PdfLegendPosition LegendPosition { get; init; } = PdfLegendPosition.Bottom;
1. ФИО студента.
2. Дата поступления /// <summary>
3. Форма обучения (выбирается из выпадающего списка). /// Значения
4. Успеваемость /// </summary>
public required IEnumerable<PdfHistogramLineInfo> Values { get; init; }
- Отображение данных в виде списка }
Данные о студентах выводятся на главной форме в виде списка строк ```
- Формирование документа в PDF:
Создается таблица с данными о средних баллах студентов по сессиям.
Колонки таблицы: сессии от 1 до 6.
Строки таблицы: средние баллы студентов (без указания ФИО).
- Формирование таблицы в excel:
Создается табличный отчет с информацией по всем студентам.
Шапка таблицы:
- Id
- ФИО
- Образование
- Форма обучения
- Дата поступления
- Создание круговой диаграммы в Word:
Формируется линейная диаграмма, отображающая распределение студентов по форме обучения,
поступивших в разнык года
| Компонент | Преимущества | Недостатки |
|--------------------------|--------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| CustomDateTimePicker | Понятные и логичные названия переменных | Занимаемое компонентом место не оптимизировано (могут возникнуть трудности с контейнерами) |
| VisualSelectionComponent | Содержит большую часть требуемого функцинонала | В базовой поставке отсутствует функционал заполнения, отсутствует xml документация, функции имеют не оправдано длинное название, границы компонента занимают чуть больше места чем вложенные элементы |
| ComponentDiagram | Реализует функционал создания диограммы в текстовом документе word | Использует комерческую библиотеку с бесплатным доступом, на документе остаётся водяной знак, в функцию создания документа передаётся объект, но его поля нужно инициализировать в конструкторе, отсутствует xml документация |
| CustomExcelTable | Удобные настройки таблицы, понятные наименования функций и классов | Отсутствует xml документация |
# Лабораторная работа №5.
# Применение структурных паттернов.
## Задание
1) Дать описание паттернов, указанных во вариантах, для каких целей они могут применяться,
какие участники там фигурируют.
2) На основе задания из 3 лабораторной работы, для каждого паттерна придумать сущности,
относящиеся к той же предметной области, что описаны в задании и реализация которых
бы в приложении потребовала применения паттерна.
### Ограничения:
- На каждый паттерн свои сущности
- В качестве источника сущностей использовать предметную область задания 3 лабораторной работы,
а не элементы разработки (что-то типа «У меня паттерн Singleton,
укажу ка я класс-подключение к БД через него», не принимается).
3) Создать диаграммы классов, отражающие взаимодействие новых
сущностей (а также используемый паттерн) с классами,
созданными в рамках 3 лабораторной работы. Отдельно отметить
классы, которые являются участниками паттерна
## Вариант 3: _Adapter, Composite, Proxy_
### Паттерн Adapter
Паттерн Адаптер используется для того,
чтобы объекты с несовместимыми интерфейсами могли работать вместе.
Он оборачивает один интерфейс в другой,
делая несовместимые классы совместимыми без изменения их исходного кода.
Задачи, которые решает паттерн Adapter:
- Интеграция стороннего кода или библиотек:
когда требуется использовать стороннюю библиотеку с вашим приложением,
но её интерфейс отличается от имеющегося интерфейса.
- Обратная совместимость: когда нужно подключить новый код к старому интерфейсу, не изменяя существующий.
- Упрощение взаимодействия: уменьшает сложность работы с несколькими несовместимыми компонентами.
Участники:
- Target: представляет объекты, которые используются клиентом.
- Client: использует объекты Target для реализации своих задач.
- Adaptee: представляет адаптируемый класс, который хотелось бы использовать у клиента вместо объектов Target.
- Adapter: сам адаптер, который позволяет работать с объектами Adaptee как с объектами Target.
**Пример реализации для рассматриваемой предметной области:**<br>
Классы, реализующие паттерн:
- IStudentTracker (Target) Интерфейс системы отслеживания успеваемости студентов
- StudentManager (Client) Использует данные о успеваемости, для определеня судьбы студентов
- AttendanceTracker (Adaptee) Реализализовывает систему отслеживания посещаемости студентов
- StudentTrackerAdapter (Adapter) "оборачивает" стороннюю систему и преобразует её в интерфейс, ожидаемый клиентом
![img_1.png](https://git.is.ulstu.ru/bekodeg/Cop.Borovkov.Var3/raw/branch/dev/Lab5-6/img_1.png)
### Паттерн Composite
Паттерн Компоновщик (Composite) объединяет группы объектов в древовидную структуру
по принципу "часть-целое и позволяет клиенту одинаково работать как с отдельными объектами,
так и с группой объектов.
Образно реализацию паттерна можно представить в виде меню,
которое имеет различные пункты. Эти пункты могут содержать подменю, в которых,
в свою очередь, также имеются пункты. То есть пункт меню служит с одной стороны частью меню,
а с другой стороны еще одним меню. В итоге мы однообразно можем работать как с пунктом меню,
так и со всем меню в целом.
Участники:
- Component определяет интерфейс для всех компонентов в древовидной структуре
- Composite представляет компонент, который может содержать другие компоненты
и реализует механизм для их добавления и удаления
- Leaf представляет отдельный компонент, который не может содержать другие компоненты
- Client клиент, который использует компоненты
Классы, реализующие паттерн:
- IStudent (Component) Студент обучающийся в вузе
- Group (Composite) Группировка студентов (групаа в потоке, поток, курс...)
- Student (Leaf) Конкретный студент
- University (Client) Обеспечивает обучение студентов
![img.png](https://git.is.ulstu.ru/bekodeg/Cop.Borovkov.Var3/raw/branch/dev/Lab5-6/img.png)
### Паттерн Proxy
Паттерн Заместитель (Proxy) предоставляет объект-заместитель, который управляет доступом к другому объекту.
То есть создается объект-суррогат, который может выступать в роли другого объекта и замещать его.
Участники:
- Subject определяет общий интерфейс для Proxy и RealSubject. Поэтому Proxy может использоваться вместо RealSubject
- RealSubject представляет реальный объект, для которого создается прокси
- Proxy заместитель реального объекта. Хранит ссылку на реальный объект, контролирует к нему доступ,
может управлять его созданием и удалением. При необходимости Proxy переадресует запросы объекту RealSubject
- Client использует объект Proxy для доступа к объекту RealSubject
Классы, реализующие паттерн:
- IStudent (Subject) Студент
- Student (RealSubject) Студент из группы
- Elder (Proxy) Староста отвечает на вопросы преподователя, при надомности спрашивает студентов группы
- Lecturer (Client) - Задаёт вопросы студентам через старосту
![img_2.png](https://git.is.ulstu.ru/bekodeg/Cop.Borovkov.Var3/raw/branch/dev/Lab5-6/img_2.png)
# Лабораторная работа №6.
# Применение структурных паттернов.
## Задание
1) Дать описание паттернов, указанных во вариантах, для каких целей они могут применяться,
какие участники там фигурируют.
2) На основе задания из 3 лабораторной работы, для каждого паттерна придумать сущности,
относящиеся к той же предметной области, что описаны в задании и реализация которых
бы в приложении потребовала применения паттерна.
### Ограничения
- На каждый паттерн свои сущности
- В качестве источника сущностей использовать предметную область задания 3 лабораторной работы,
а не элементы разработки (что-то типа «У меня паттерн Singleton,
укажу ка я класс-подключение к БД через него», не принимается).
3) Создать диаграммы классов, отражающие взаимодействие новых
сущностей (а также используемый паттерн) с классами,
созданными в рамках 3 лабораторной работы. Отдельно отметить
классы, которые являются участниками паттерна
## Вариант 3 _AbstractFactory, FactoryMethod, ObjectPool._
### Паттерн AbstractFactory
Паттерн "Абстрактная фабрика" (Abstract Factory) предоставляет интерфейс для создания семейств
взаимосвязанных объектов с определенными интерфейсами без указания конкретных типов данных объектов.
Участники
- AbstractProductA и AbstractProductB абстрактные классы, определяющие интерфейс для классов,
объекты которых будут создаваться в программе
- ProductA1 / ProductA2 и ProductB1 / ProductB2 конкретные классы,
представляющие конкретную реализацию абстрактных классов.
- AbstractFactory - Абстрактный класс фабрики определяет методы для создания объектов.
Причем методы возвращают абстрактные продукты, а не их конкретные реализации.
- Client класс клиента, использующий класс фабрики для создания объектов.
При этом он использует исключительно абстрактный класс фабрики AbstractFactory
и абстрактные классы продуктов AbstractProductA и AbstractProductB и никак не зависит от их конкретных реализаций.
Классы, реализующие паттерн:
- IReportFactory (Abstract Factory) интерфейс фабрики для создания отчетов.
- FivePointReportFactory (Concrete Factory) фабрика для 5-балльной системы.
- HundredPointReportFactory (Concrete Factory) фабрика для 100-балльной системы.
- IPerformanceReport (Abstract Product) интерфейс для отчета по успеваемости.
- FivePointPerformanceReport и HundredPointPerformanceReport (Concrete Products) конкретные реализации отчетов по успеваемости для 5- и 10-балльной систем.
- ILaggingStudentsReport (Abstract Product) интерфейс для отчета по отстающим студентам.
- FivePointLaggingStudentsReport и HundredPointLaggingStudentsReport (Concrete Products) отчеты по отстающим студентам для 5- и 10-балльной систем.
- ReportManager (Client) класс, который обрабатывает отчеты
![img_4.png](https://i.pinimg.com/originals/43/89/ed/4389ed56415070fc606be04621db69cc.jpg)
### Паттерн FactoryMethod
Фабричный метод (Factory Method) - это паттерн, который определяет интерфейс для создания объектов некоторого класса,
но непосредственное решение о том, объект какого класса создавать происходит в подклассах.
То есть паттерн предполагает, что базовый класс делегирует создание объектов классам-наследникам.
Участники:
- Product интерфейс или абстрактный класс, определяющий структуру создаваемых объектов.
- ConcreteProductA и ConcreteProductB конкретные реализации интерфейса “Product”, представляющие первый и второй тип продукта.
- Creator абстрактный класс или интерфейс, который определяет фабричный метод для создания объектов типа “Product”.
- ConcreteCreatorA и ConcreteCreatorB конкретные реализации “Creator”, которая создаёт объекты типа “ConcreteProductA” и “ConcreteCreatorB” соответственно.
Классы, реализующие паттерн:
- Product IReport определяет интерфейс для всех отчетов.
- ConcreteProductA и ConcreteProductB GradeReport и AttendanceReport конкретные реализации интерфейса “IReport”.
- Creator ReportCreator определяет фабричный метод для создания объектов типа “IReport”.
- ConcreteCreatorA и ConcreteCreatorB GradeReportCreator и AttendanceReportCreator конкретные реализации “ReportCreator”.
![img_5.png](https://git.is.ulstu.ru/bekodeg/Cop.Borovkov.Var3/raw/branch/dev/Lab5-6/img_1.png)
### Паттерн ObjectPool
Object Pool (пул объектов) — это поведенческий паттерн, который используется для оптимизации управления ресурсами.
Он позволяет многократно использовать уже созданные объекты вместо их повторного создания и уничтожения.
Это особенно полезно, когда создание объектов является дорогой операцией с точки зрения времени или ресурсов.
Участники:
- Pool управляет коллекцией объектов. Отвечает за выдачу и возврат объектов из пула. Решает, когда создавать новый объект или использовать существующий.
- ReusableObject (повторно используемый объект) - объект, который находится в пуле и может быть многократно использован. Включает логику и состояние объекта.
- Client - получает объект из пула для использования. Возвращает объект обратно в пул, когда он больше не нужен.
Классы, реализующие паттерн:
- Pool FormatPool управляет доступностью объектов “Format”. Позволяет выдавать объекты формы обучения для студентов.
- ReusableObject Format содержит данные, связанные с конкретной формой обучения.
- Client Student представляет студента и содержит данные о нем.
![img_6.png](https://git.is.ulstu.ru/bekodeg/Cop.Borovkov.Var3/raw/branch/dev/Lab5-6/img_6.png)
# Лабораторная работа №7.
# Применение структурных паттернов.
## Задание
1) Дать описание паттернов, указанных во вариантах, для каких целей они могут применяться,
какие участники там фигурируют.
2) На основе задания из 3 лабораторной работы, для каждого паттерна придумать сущности,
относящиеся к той же предметной области, что описаны в задании и реализация которых
бы в приложении потребовала применения паттерна.
### Ограничения
- На каждый паттерн свои сущности
- В качестве источника сущностей использовать предметную область задания 3 лабораторной работы,
а не элементы разработки (что-то типа «У меня паттерн Singleton,
укажу ка я класс-подключение к БД через него», не принимается).
3) Создать диаграммы классов, отражающие взаимодействие новых
сущностей (а также используемый паттерн) с классами,
созданными в рамках 3 лабораторной работы. Отдельно отметить
классы, которые являются участниками паттерна
## Вариант 3 _Mediator, Mediator (2 различных реализации), Strategy._
### Паттерн Mediator
Паттерн "Посредник" (Mediator) представляет такой шаблон проектирования,
который обеспечивает взаимодействие множества объектов без необходимости ссылаться друг на друга.
Тем самым достигается слабосвязанность взаимодействующих объектов.
Участники
- Mediator - представляет интерфейс для взаимодействия с объектами Colleague.
- Colleague - представляет интерфейс для взаимодействия с объектом Mediator.
- ConcreteColleague1 и ConcreteColleague2 - конкретные классы коллег,
которые обмениваются друг с другом через объект Mediator.
- ConcreteMediator - конкретный посредник, реализующий интерфейс типа Mediator.
Классы, реализующие паттерн:
- Secretary Mediator - Секретарь
- Client Colleague - Участник вузовской системы
- Teacher ConcreteColleague1 - Преподователь
- Student ConcreteColleague2 - Студент
- Dean`s Office ConcreteMediator - Деканат
![img_8.png](https://i.pinimg.com/originals/7f/c3/40/7fc340de38957f5c29de3a6a6689a252.png)
- ILms Mediator - Сайт лмс
- User Colleague - Пользователь лмс
- Teacher ConcreteColleague1 - Преподователь
- Student ConcreteColleague2 - Студент
- Lms ConcreteMediator - Логика сайта лмс
![img_7.png](https://i.pinimg.com/originals/ac/c5/67/acc567be76d33349c35fd5fc10f84b9f.jpg)
### Паттерн Strategy
Strategy (Стратегия) — шаблон проектирования, который определяет набор алгоритмов, инкапсулирует каждый из них и обеспечивает их взаимозаменяемость. В зависимости от ситуации мы можем легко заменить один используемый алгоритм другим. При этом замена алгоритма происходит независимо от объекта, который использует данный алгоритм.
Участники:
- IStrategy: интерфейс, который определяет метод Algorithm(). Это общий интерфейс для всех реализующих его алгоритмов. Вместо интерфейса здесь также можно было бы использовать абстрактный класс.
- ConcreteStrategy1 и ConcreteStrategy2: классы, которые реализуют интерфейс IStrategy, предоставляя свою версию метода Algorithm(). Подобных классов-реализаций может быть множество.
- Context: класс, который хранит ссылку на объект IStrategy и связан с интерфейсом IStrategy отношением агрегации.
Классы, реализующие паттерн:
- IStrategy IReportStrategy общий интерфейс для всех стратегий формирования отчетов.
- PdfReportStrategy, ExcelkReportStrategy, WordReportStrategy - классы, реализующие формирование отчета в pdf, excel и word.
- Context ReportContext контекст, который использует стратегию для формирования отчета.
Этот подход позволяет легко добавлять новые форматы отчетов (например, JSON или HTML) без изменения существующего кода, реализуя принцип открытости/закрытости.
![img_9.png](https://git.is.ulstu.ru/bekodeg/Cop.Borovkov.Var3/media/branch/dev/Lab5-6/img_10.png)

Binary file not shown.