Compare commits

..

No commits in common. "master" and "net7-final" have entirely different histories.

101 changed files with 804 additions and 4693 deletions

View File

@ -1,4 +0,0 @@
[*.cs]
# SYSLIB1045: Преобразовать в "GeneratedRegexAttribute".
dotnet_diagnostic.SYSLIB1045.severity = silent

View File

@ -1,5 +1,10 @@
# Что такое ANB Software Components Pack? # anbsoftware_componentspack
ANB Software Components Pack - набор полезных классов C#, которые расширяют возможности языка. Они могут использоваться в приложенях для ОС Widows и серверов на базе этой ОС. some classes that extend the capabilities of the C # language
# Лицензия # Welcome to ANB Software Components Pack!
MIIT
You are on the component set «ANB» page. Thanks for your interest in the project
# License
MIIT

View File

@ -0,0 +1,63 @@
using anbs_cp.Interfaces;
namespace anbs_cp.Classes;
/// <summary>
/// Класс ошибки
/// </summary>
public sealed class ActionError: IActionError
{
/// <summary>
/// Критичность ошибки:
/// при некритичных ошибках продолжение выполнения операции возможно,
/// а при критичных -- нет
/// </summary>
public bool IsCritical { get; init; }
/// <summary>
/// Объект ошибки
/// </summary>
public object Object { get; set; }
/// <summary>
/// Сообщение об ошибке
/// </summary>
public string Message { get; set; }
#region Конструкторы
/// <summary>
/// Конструктор по умолчанию
/// </summary>
public ActionError ()
{
IsCritical = true;
Object = "Not Implemented";
Message = "Not Implemented";
}
/// <summary>
/// Конструктор с 2 параметрами
/// </summary>
/// <param name="message">Сообщение</param>
/// <param name="isCritical">Критичность ошибки</param>
public ActionError (string message, bool isCritical = true)
{
IsCritical = isCritical;
Object = "";
Message = message;
}
/// <summary>
/// Конструктор с 3 параметрами
/// </summary>
/// <param name="eObject">Объект ошибки</param>
/// <param name="message">Сообщение</param>
/// <param name="isCritical">Критичность ошибки</param>
public ActionError (object eObject, string message, bool isCritical = true)
{
IsCritical = isCritical;
Object = eObject;
Message = message;
}
#endregion
}

View File

@ -0,0 +1,49 @@
using anbs_cp.Interfaces;
namespace anbs_cp.Classes;
/// <summary>
/// Класс предупреждения
/// </summary>
public sealed class ActionInfo: IActionInfo
{
#region Конструкторы
/// <summary>
/// Конструктор по умолчанию
/// </summary>
public ActionInfo ()
{
IsStatusInfo = false;
Object = string.Empty;
Message = string.Empty;
}
/// <summary>
/// Конструктор
/// </summary>
/// <param name="eObject">Объект</param>
/// <param name="message">Сообщение</param>
/// <param name="isStatus">Является статусной информацией?</param>
public ActionInfo (string eObject, string message, bool isStatus = false)
{
IsStatusInfo = isStatus;
Object = eObject;
Message = message;
}
#endregion
#region Реализация интерфейса
/// <summary>
/// Объект
/// </summary>
public object Object { get; set; }
/// <summary>
/// Сообщение
/// </summary>
public string Message { get; set; }
/// <summary>
/// Статусная информация (например, начало работы)
/// </summary>
public bool IsStatusInfo { get; init; }
#endregion
}

View File

@ -1,65 +1,71 @@
// ReSharper disable MemberCanBePrivate.Global using anbs_cp.Interfaces;
// ReSharper disable UnusedAutoPropertyAccessor.Global
// ReSharper disable MemberCanBeProtected.Global
using anbs_cp.Enums;
using anbs_cp.Interfaces;
namespace anbs_cp.Classes; namespace anbs_cp.Classes;
/*
История версий
Обновлено 2024.03.28
* Все поля Errors, Warnings и Infos объеденины в одно Messages
* В ActionStateMessage добавлен параметр, определяющий тип: MessageType
Обновлено 2024.03.26
* Все интерфейсы объеденины в один класс ActionStateMessage
* Интерфейс IActionState удалён
Обновлено 2023.12.10
* Заменены классы Action* на соответствующие интерфейсы
* Класс ActionState теперь наследует интерфейс IActionState, позволяющий добавлять состояния (ошибки, предупреждения и информацию)
из разных классов ActionState, т.е. например, данные из ActionState<bool> (кроме значения!) можно перенести в ActionState<int>.
Обновлено 2023.11.1
* Добавлен возвращаемый результат
Обновлено 2023.01.121.1:
* Заменены интерфейсы IAction* на соответствующие классы
*/
/// <summary> /// <summary>
/// Состояние действия /// Состояние действия
///
/// Обновлено 2023.11.1
/// * Добавлен возвращаемый результат
///
/// Обновлено 2023.01.121.1:
/// * Заменены интерфейсы IAction* на соответствующие классы
/// </summary> /// </summary>
/// <typeparam name="T">Тип класса</typeparam> public class ActionState<T>
public class ActionState<T>: ISerializable
{ {
/// <summary>
/// Конструктор по умолчанию
/// </summary>
public ActionState ()
{
Info = new();
Warnings = new();
Errors = new();
Value = default;
}
/// <summary>
/// Конструктор с указанием начального значения <see cref="Value"/>
/// </summary>
/// <param name="defaultValue">Начальное значение <see cref="Value"/></param>
public ActionState (T defaultValue)
{
Info = new();
Warnings = new();
Errors = new();
Value = defaultValue;
}
/// <summary> /// <summary>
/// Список информации /// Список информации
/// </summary> /// </summary>
// ReSharper disable once CollectionNeverQueried.Local public List<ActionInfo> Info { get; }
internal List<ActionStateMessage> Messages { get; } = [];
/// <summary>
/// Список предупреждений
/// </summary>
public List<ActionWarning> Warnings { get; }
/// <summary>
/// Список ошибок
/// </summary>
public List<ActionError> Errors { get; }
/// <summary> /// <summary>
/// Значение /// Значение
/// </summary> /// </summary>
public T? Value { get; set; } public T? Value { get; set; }
/// <summary>
/// Метод для выбора всех значений для условия
/// </summary>
// ReSharper disable once StaticMemberInGenericType
public static readonly Func<ActionStateMessage, bool> SelectAll = static _ => true;
#region Методы #region Методы
#region Очистка #region Очистка
/// <summary> /// <summary>
/// Очищает список ошибок /// Очищает список ошибок
/// </summary> /// </summary>
public void ClearErrors () public void ClearErrors ()
{ {
Clear(static message => message.MessageType == EActionStateMessageType.Error); Errors.Clear();
Errors.TrimExcess();
} }
/// <summary> /// <summary>
@ -67,7 +73,8 @@ public class ActionState<T>: ISerializable
/// </summary> /// </summary>
public void ClearWarnings () public void ClearWarnings ()
{ {
Clear(static message => message.MessageType == EActionStateMessageType.Warning); Warnings.Clear();
Warnings.TrimExcess();
} }
/// <summary> /// <summary>
@ -75,56 +82,62 @@ public class ActionState<T>: ISerializable
/// </summary> /// </summary>
public void ClearInfo () public void ClearInfo ()
{ {
Clear(static message => message.MessageType == EActionStateMessageType.Information); Info.Clear();
Info.TrimExcess();
} }
/// <summary> /// <summary>
/// Очищает список по условию <paramref name="predicate"/> /// Очищает все списки
/// </summary> /// </summary>
/// <param name="predicate">Условие выборки</param> public void Clear ()
public void Clear (Func<ActionStateMessage, bool> predicate)
{ {
// Получаю список элементов ClearInfo();
IEnumerable<ActionStateMessage> list = Messages.Where(predicate); ClearWarnings();
ClearErrors();
// Для каждого элемента
foreach (ActionStateMessage actionStateMessage in list)
// - запускаю его удаление
Messages.Remove(actionStateMessage);
} }
#endregion #endregion
#region Добавление
/// <summary>
/// Добавление сообщения
/// </summary>
/// <param name="message">Сообщение</param>
// ReSharper disable once MemberCanBeMadeStatic.Global
// ReSharper disable once FunctionRecursiveOnAllPaths
public void Add (ActionStateMessage message) => Messages.Add(message);
/// <summary>
/// Добавляет список
/// </summary>
/// <param name="messages">Список сообщений</param>
public void AddRange (IEnumerable<ActionStateMessage> messages) => Messages.AddRange(messages);
#endregion
#region Добавление ошибки #region Добавление ошибки
/// <summary>
/// Добавление ошибки
/// </summary>
/// <param name="error">Ошибка</param>
// ReSharper disable once MemberCanBeMadeStatic.Global
// ReSharper disable once FunctionRecursiveOnAllPaths
public void AddError (ActionError error) => Errors.Add(error);
/// <summary>
/// Добавляет ошибки в список
/// </summary>
/// <param name="errors">Список ошибок</param>
public void AddErrors(IEnumerable<ActionError> errors) => Errors.AddRange(errors);
/// <summary> /// <summary>
/// Добавление ошибки /// Добавление ошибки
/// </summary> /// </summary>
/// <param name="critical">Является ли ошибка критической</param> /// <param name="critical">Является ли ошибка критической</param>
public void AddError (bool critical = true) => Add(new(EActionStateMessageType.Error, critical)); public void AddError (bool critical = true)
{
//Создаю ошибку
ActionError error = new("", critical);
//Добавляю ошибку
AddError(error);
}
/// <summary> /// <summary>
/// Добавление ошибки /// Добавление ошибки
/// </summary> /// </summary>
/// <param name="message">Сообщение об ошибке</param> /// <param name="message">Сообщение об ошибке</param>
/// <param name="critical">Является ли ошибка критической</param> /// <param name="critical">Является ли ошибка критической</param>
public void AddError (string message, bool critical = true) => public void AddError (string message, bool critical = true)
Add(new(EActionStateMessageType.Error, critical, message: message)); {
//Создаю ошибку
ActionError error = new(message, critical);
//Добавляю ошибку
AddError(error);
}
/// <summary> /// <summary>
/// Добавление ошибки /// Добавление ошибки
@ -132,71 +145,118 @@ public class ActionState<T>: ISerializable
/// <param name="errorObject">Объект ошибки</param> /// <param name="errorObject">Объект ошибки</param>
/// <param name="message">Сообщение об ошибке</param> /// <param name="message">Сообщение об ошибке</param>
/// /// <param name="critical">Является ли ошибка критической</param> /// /// <param name="critical">Является ли ошибка критической</param>
public void AddError (string errorObject, string message, bool critical = true) => public void AddError (string errorObject, string message, bool critical = true)
Add(new(EActionStateMessageType.Error, critical, errorObject, message)); {
//Создаю ошибку
ActionError error = new(errorObject, message, critical);
//Добавляю ошибку
AddError(error);
}
#endregion #endregion
#region Добавление предупреждения #region Добавление предупреждения
/// <summary>
/// Добавление предупреждения
/// </summary>
/// <param name="warning">Предупреждение</param>
public void AddWarning (ActionWarning warning) => Warnings.Add(warning);
/// <summary>
/// Добавление предупреждений
/// </summary>
/// <param name="warnings">Список предупреждений</param>
public void AddWarnings(IEnumerable<ActionWarning> warnings) => Warnings.AddRange(warnings);
/// <summary> /// <summary>
/// Добавление предупреждение /// Добавление предупреждение
/// </summary> /// </summary>
/// <param name="message">Текст предупреждения</param> /// <param name="message">Текст предупреждения</param>
/// <param name="warningObject">Объект предупреждения</param> /// <param name="warningObject">Объект предупреждения</param>
public void AddWarning (string message, string warningObject = "") => public void AddWarning (string message, string warningObject = "")
Add(new(EActionStateMessageType.Warning, message: message, obj: warningObject)); {
//Создаю предупреждение
ActionWarning warning = new(warningObject, message);
//Добавляю предупреждение
AddWarning(warning);
}
#endregion #endregion
#region Добавление информации #region Добавление информации
/// <summary>
/// Добавление информации
/// </summary>
/// <param name="info">Информация</param>
public void AddInfo (ActionInfo info) => Info.Add(info);
/// <summary>
/// Добавление информации
/// </summary>
/// <param name="infos">Список информации</param>
public void AddInfos (IEnumerable<ActionInfo> infos) => Info.AddRange(infos);
/// <summary> /// <summary>
/// Добавление информации /// Добавление информации
/// </summary> /// </summary>
/// <param name="message">Текст информации</param> /// <param name="message">Текст информации</param>
/// <param name="infoObject">Объект информации</param> /// <param name="infoObject">Объект информации</param>
public void AddInfo (string message, string infoObject = "") => Add(new(message: message, obj: infoObject)); public void AddInfo (string message, string infoObject = "")
{
//Создаю информацию
ActionInfo info = new(infoObject, message);
//Добавляю информацию
AddInfo(info);
}
#endregion #endregion
#region Печать #region Печать
/// <summary> /// <summary>
/// Печать сообщений /// Печать списка ошибок
/// </summary> /// </summary>
/// <param name="area">Область печати</param> /// <param name="formatList">Формат списка</param>
/// <param name="formatList">Оформление всей области</param> /// <param name="formatItem">Формат элемента списка</param>
/// <param name="formatItem">Оформление элемента</param> /// <returns>Список ошибок в текстовой форме</returns>
/// <returns>Текстовое представление выбранных списокв</returns> public string PrintErrorList (string formatList, string formatItem)
/// <exception cref="ArgumentOutOfRangeException">Ошибка при неизвестной области</exception>
public string PrintMessage (EActionStatePrintArea area, string formatList, string formatItem)
{ {
// Создаю список
List<ActionStateMessage> list = [];
// Выбираю списки по областям
switch (area)
{
case EActionStatePrintArea.All:
list.AddRange(Messages);
break;
case EActionStatePrintArea.ErrorsAndWarnings:
list.AddRange(Messages.Where(static message =>
message.MessageType is EActionStateMessageType.Error or EActionStateMessageType.Warning));
break;
case EActionStatePrintArea.ErrorsOnly:
list.AddRange(Messages.Where(static message => message.MessageType == EActionStateMessageType.Error));
break;
case EActionStatePrintArea.WarningsOnly:
list.AddRange(Messages.Where(static message => message.MessageType == EActionStateMessageType.Warning));
break;
case EActionStatePrintArea.InfosOnly:
list.AddRange(Messages.Where(static message =>
message.MessageType == EActionStateMessageType.Information));
break;
default:
throw new ArgumentOutOfRangeException(nameof(area), area, null);
}
// Создаю элементы
string elements = string elements =
list.Aggregate(string.Empty, (current, item) => current + item.PrintMessage(formatItem)); #pragma warning disable CS8625
Errors.Aggregate<IActionError, string>(null, (current, error) => current + error.PrintMessage(formatItem));
#pragma warning restore CS8625
return string.Format(formatList, elements);
}
/// <summary>
/// Печать списка предупреждений
/// </summary>
/// <param name="formatList">Формат списка</param>
/// <param name="formatItem">Формат элемента списка</param>
/// <returns>Список предупреждений в текстовой форме</returns>
public string PrintWarningList (string formatList, string formatItem)
{
string elements =
#pragma warning disable CS8625
Warnings.Aggregate<IActionWarning, string>(null,
#pragma warning restore CS8625
(current, warning) => current + warning.PrintMessage(formatItem));
return string.Format(formatList, elements);
}
/// <summary>
/// Печать списка информации
/// </summary>
/// <param name="formatList">Формат списка</param>
/// <param name="formatItem">Формат элемента списка</param>
/// <returns>Список информации в текстовой форме</returns>
public string PrintInfoList (string formatList, string formatItem)
{
string elements =
#pragma warning disable CS8625
Info.Aggregate<IActionInfo, string>(null, (current, info) => current + info.PrintMessage(formatItem));
#pragma warning restore CS8625
return string.Format(formatList, elements); return string.Format(formatList, elements);
} }
@ -208,24 +268,24 @@ public class ActionState<T>: ISerializable
/// </summary> /// </summary>
/// <param name="ignoreNonCritical">Игнорировать не критические</param> /// <param name="ignoreNonCritical">Игнорировать не критические</param>
/// <returns>Наличие ошибок</returns> /// <returns>Наличие ошибок</returns>
public bool HasErrors (bool ignoreNonCritical = false) => Messages.Any(message => public bool HasErrors (bool ignoreNonCritical = false) =>
message.MessageType == EActionStateMessageType.Error && (!ignoreNonCritical || !message.IsCritical)); ignoreNonCritical ? Errors.Any(static error => error.IsCritical) : Errors.Any();
/// <summary> /// <summary>
/// Проверяет, есть ли предупреждения /// Проверяет, есть ли предупреждения
/// </summary> /// </summary>
/// <param name="ignoreInformWarning">Игнорировать информационные предупреждения</param> /// <param name="ignoreInformWarning">Игнорировать информационные предупреждения</param>
/// <returns>Наличие предупреждений</returns> /// <returns>Наличие предупреждений</returns>
public bool HasWarnings (bool ignoreInformWarning = false) => Messages.Any(message => public bool HasWarnings (bool ignoreInformWarning = false) => ignoreInformWarning
message.MessageType == EActionStateMessageType.Warning && (!ignoreInformWarning || !message.IsCritical)); ? Warnings.Any(static warning => !warning.IsInformWarning)
: Warnings.Any();
/// <summary> /// <summary>
/// Проверяет, есть ли сообщения /// Проверяет, есть ли сообщения
/// </summary> /// </summary>
/// <param name="ignoreStatus">Игнорировать статусные сообщения</param> /// <param name="ignoreStatus">Игнорировать статусные сообщения</param>
/// <returns>Наличие сообщений</returns> /// <returns>Наличие сообщений</returns>
public bool HasInfo (bool ignoreStatus) => Messages.Any(message => public bool HasInfo (bool ignoreStatus) => ignoreStatus ? Info.Any(static info => !info.IsStatusInfo) : Info.Any();
message.MessageType == EActionStateMessageType.Information && (!ignoreStatus || !message.IsCritical));
/// <summary> /// <summary>
/// Успешно ли завершилось /// Успешно ли завершилось
@ -235,36 +295,29 @@ public class ActionState<T>: ISerializable
#endregion #endregion
#region Количество сообщений #region Количество сообщений
/// <summary>
/// Количество сообщений, удовлеьворяющих условию <paramref name="predicate"/>
/// </summary>
/// <param name="predicate">Условие выборки</param>
/// <returns>Число сообщений</returns>
public int Count (Func<ActionStateMessage, bool> predicate) => Messages.Count(predicate);
/// <summary> /// <summary>
/// Количество ошибок /// Количество ошибок
/// </summary> /// </summary>
/// <param name="ignoreNonCritical">Игнорировать не критические</param> /// <param name="ignoreNonCritical">Игнорировать не критические</param>
/// <returns>Количество ошибок</returns> /// <returns>Количество ошибок</returns>
public int ErrorsCount (bool ignoreNonCritical = false) => Count(message => public int ErrorsCount (bool ignoreNonCritical = false) =>
message.MessageType == EActionStateMessageType.Error && (!ignoreNonCritical || !message.IsCritical)); ignoreNonCritical ? Errors.Count(static error => error.IsCritical) : Errors.Count;
/// <summary> /// <summary>
/// Количество предупреждений /// Количество предупреждений
/// </summary> /// </summary>
/// <param name="ignoreInformWarning">Игнорировать информационные предупреждения</param> /// <param name="ignoreInformWarning">Игнорировать информационные предупреждения</param>
/// <returns>Количество предупреждений</returns> /// <returns>Количество предупреждений</returns>
public int WarningsCount (bool ignoreInformWarning = false) => Count(message => public int WarningsCount (bool ignoreInformWarning = false) => ignoreInformWarning
message.MessageType == EActionStateMessageType.Warning && (!ignoreInformWarning || !message.IsCritical)); ? Warnings.Count(static warning => !warning.IsInformWarning)
: Warnings.Count;
/// <summary> /// <summary>
/// Количество информационных сообщений /// Количество информационных сообщений
/// </summary> /// </summary>
/// <param name="ignoreStatus">Игнорировать статусные сообщения</param> /// <param name="ignoreStatus">Игнорировать статусные сообщения</param>
/// <returns>Количество информационных сообщений</returns> /// <returns>Количество информационных сообщений</returns>
public int InfoCount (bool ignoreStatus) => Count(message => public int InfoCount (bool ignoreStatus) => ignoreStatus ? Info.Count(static info => !info.IsStatusInfo) : Info.Count;
message.MessageType == EActionStateMessageType.Information && (!ignoreStatus || !message.IsCritical));
#endregion #endregion
#region Добавление другого состояния #region Добавление другого состояния
@ -272,69 +325,13 @@ public class ActionState<T>: ISerializable
/// <summary> /// <summary>
/// Добавляет другое состояние (например, результат другого действия, который возвращает <see cref="ActionState"/>). /// Добавляет другое состояние (например, результат другого действия, который возвращает <see cref="ActionState"/>).
/// </summary> /// </summary>
/// <typeparam name="TO">Тип параметра</typeparam>
/// <param name="state">Запись состояния</param> /// <param name="state">Запись состояния</param>
public void AddState<TO> (ActionState<TO> state) => AddRange(state.Messages); public void AddState(ActionState state)
#endregion
#endregion
#region Реализация интерфейса ISerializable
/// <inheritdoc />
public string Serialize ()
{ {
// Создаю модель AddErrors(state.Errors);
ActionStateSerializable serializableModel = new(); AddWarnings(state.Warnings);
AddInfos(state.Info);
// Для каждого сообщения
foreach (ActionStateMessage message in Messages)
// - добавляю в модель
serializableModel.Messages.Add(message.Serialize());
// Создаю модель значения
ActionStateSerializableValue value = new();
// Получаю данные
value.GetValue(Value);
// Добавляю в модель
serializableModel.Value = value.Serialize();
// Возвращаю сериализованную модель
return new NewtonsoftJsonSerializer().Serialize(serializableModel);
}
/// <inheritdoc />
public void Deserialize (string json)
{
// Удаляю лишние символы
json = json.Trim("\"".ToCharArray());
// Десериализую строку
ActionStateSerializable itemSerializable =
new NewtonsoftJsonSerializer().Deserialize<ActionStateSerializable>(json) ?? new();
// Создаю модель значения
ActionStateSerializableValue value = new();
// Очищаю списки
Clear(SelectAll);
// Для каждого сообщения
foreach (string messageString in itemSerializable.Messages)
{
// - создаю сообщение
ActionStateMessage message = new();
// - десериализую в него данные из модели
message.Deserialize(messageString);
// - добавляю в список
Add(message);
}
// Десериализую данные значения из модели
value.Deserialize(itemSerializable.Value);
// Получаю значение
Value = value.SetValue<T>();
} }
#endregion #endregion
#endregion
} }

View File

@ -1,115 +0,0 @@
// ReSharper disable MemberCanBeInternal
// ReSharper disable MemberCanBePrivate.Global
using anbs_cp.Enums;
using anbs_cp.Interfaces;
namespace anbs_cp.Classes;
/// <summary>
/// Класс сообщения состояния
/// </summary>
public sealed class ActionStateMessage (
EActionStateMessageType type = EActionStateMessageType.Information,
bool isCritical = false,
string obj = "",
string message = ""): ISerializable
{
#region Свойства
/// <summary>
/// Тип сообщения
/// </summary>
public EActionStateMessageType MessageType { get; set; } = type;
/// <summary>
/// Критичность сообщения
/// </summary>
public bool IsCritical { get; set; } = isCritical;
/// <summary>
/// Объект сообщения
/// </summary>
public string Object { get; set; } = obj;
/// <summary>
/// Текст сообщения
/// </summary>
public string Message { get; set; } = message;
#endregion
#region Методы
/// <summary>
/// Вывод сообщения
/// </summary>
/// <param name="format">Строка-форматирование (например, «[{0}] - {1}»)</param>
/// <returns>Отформатированную строка</returns>
public string PrintMessage (string format) => string.Format(format, Object, Message);
/// <summary>
/// Устанавливает объект
/// </summary>
/// <param name="obj">Объект</param>
/// <typeparam name="T">Тип объекта</typeparam>
public void SetObject<T> (T obj)
{
// Если объект реализует интерфейс ISerializable
if (obj is ISerializable serializable)
{
// - то сериализуем его методами интерфейса
Object = serializable.Serialize();
// - и прерываем
return;
}
// Сериализуем объект с помощью NewtonsoftJson
Object = new NewtonsoftJsonSerializer().Serialize(obj);
}
/// <summary>
/// Получает объект
/// </summary>
/// <typeparam name="T">Класс объекта</typeparam>
/// <returns>Объект или null</returns>
public T? GetObject<T> () => new NewtonsoftJsonSerializer().Deserialize<T>(Object);
/// <summary>
/// Получает объект
/// </summary>
/// <typeparam name="T">Класс объекта, реализующий интерфейс ISerializable</typeparam>
/// <returns>Объект</returns>
public T GetSerializedObject<T> () where T : ISerializable, new()
{
// Создаём результирующую модель
T model = new();
// Десериализуем её методами интерфейса ISerializable
model.Deserialize(Object);
// Возвращаем модель
return model;
}
#endregion
#region Реализация интерфейса ISerializable
/// <inheritdoc />
public string Serialize () => new NewtonsoftJsonSerializer().Serialize(this);
/// <inheritdoc />
public void Deserialize (string json)
{
// Десериализую строку
ActionStateMessage item = new NewtonsoftJsonSerializer().Deserialize<ActionStateMessage>(json) ?? new();
// Передаю параметры
MessageType = item.MessageType;
IsCritical = item.IsCritical;
Object = item.Object;
Message = item.Message;
}
#endregion
}

View File

@ -1,18 +0,0 @@
// ReSharper disable CollectionNeverUpdated.Global
namespace anbs_cp.Classes;
/// <summary>
/// Сериализованная модель класса, хранящего в себе состояния действия
/// </summary>
public class ActionStateSerializable
{
/// <summary>
/// Список всех сообщений
/// </summary>
public List<string> Messages { get; } = [];
/// <summary>
/// Значение
/// </summary>
public string Value { get; set; } = string.Empty;
}

View File

@ -1,96 +0,0 @@
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable MemberCanBeInternal
using anbs_cp.Interfaces;
namespace anbs_cp.Classes;
/// <summary>
/// Сериализованная модель значения класса, хранящего в себе состояния действия
/// </summary>
public sealed class ActionStateSerializableValue: ISerializable
{
/// <summary>
/// Значение - null?
/// </summary>
public bool IsNull { get; set; }
/// <summary>
/// Сериализуемое значение
/// </summary>
public string Serialized { get; set; } = string.Empty;
/// <summary>
/// Получает значение из <paramref name="value"/>
/// </summary>
/// <param name="value">Значение</param>
/// <typeparam name="T">Тип значения</typeparam>
internal void GetValue<T> (T? value)
{
// Значение - null?
IsNull = value is null;
// Если не null
// - сериализую
Serialized = value is not null ? new SysTextSerializer().Serialize(value) : string.Empty;
}
/// <summary>
/// Устанавливает значение
/// </summary>
/// <typeparam name="T">Класс</typeparam>
/// <returns>Значение</returns>
internal T? SetValue<T> () => IsNull ? default : new SysTextSerializer().Deserialize<T>(Serialized);
/// <summary>
/// Получает значение из <paramref name="value"/>
/// </summary>
/// <param name="value">Значение</param>
/// <typeparam name="T">Тип значения</typeparam>
internal void GetSerializedValue<T> (T? value) where T : ISerializable, new()
{
// Значение - null?
IsNull = value is null;
// Если не null
// - сериализую
Serialized = value is not null ? value.Serialize() : string.Empty;
}
/// <summary>
/// Устанавливает значение
/// </summary>
/// <typeparam name="T">Класс</typeparam>
/// <returns>Значение</returns>
internal T? SetSerializedValue<T> () where T : ISerializable, new()
{
// Если null
if (IsNull)
// - то возвращаем null
return default;
// Создаю модель
T model = new ();
// Десериализую модель
model.Deserialize(Serialized);
// Возвращаю модель
return model;
}
#region Реализация интерфейса ISerializable
/// <inheritdoc />
public string Serialize () => new SysTextSerializer().Serialize(this);
/// <inheritdoc />
public void Deserialize (string json)
{
// Десериализую строку
ActionStateSerializableValue item = new SysTextSerializer().Deserialize<ActionStateSerializableValue>(json) ?? new();
// Передаю параметры
IsNull = item.IsNull;
Serialized = item.Serialized;
}
#endregion
}

View File

@ -1,86 +0,0 @@
using anbs_cp.Exceptions;
using anbs_cp.Interfaces;
namespace anbs_cp.Classes;
/// <summary>
/// Состояние действия
///
/// Обновлено 2024.03.26
/// * Добавлен класс ActionState для классов, поддерживаемых интерфейс I
/// </summary>
public sealed class ActionStateSerialized<T>: ActionState<T> where T : ISerializable, new()
{
/// <summary>
/// Добавляет другое состояние (например, результат другого действия, который возвращает <see cref="ActionState"/>).
/// </summary>
/// <param name="state">Запись состояния</param>
public void AddState (ActionStateSerialized<T> state)
{
base.AddState(state);
}
#region Переопределение реализации интерфейса ISerializable
/// <summary>
/// Сериализовать элемент в формат json
/// </summary>
/// <returns>Строка в формате json</returns>
/// <exception cref="SerializeException">Ошибка при сериализации</exception>
public new string Serialize ()
{
// Создаю модель
ActionStateSerializable serializableModel = new();
// Для каждого сообщения
foreach (ActionStateMessage message in Messages)
// - добавляю в модель
serializableModel.Messages.Add(message.Serialize());
// Создаю модель значения
ActionStateSerializableValue value = new();
// Получаю данные
value.GetSerializedValue(Value);
// Добавляю в модель
serializableModel.Value = value.Serialize();
// Возвращаю сериализованную модель
return new SysTextSerializer().Serialize(serializableModel);
}
/// <summary>
/// Восстановить элемент из формата json
/// </summary>
/// <param name="json">Строка в формате json</param>
/// <exception cref="SerializeException">Ошибка при десериализации</exception>
public new void Deserialize (string json)
{
// Десериализую строку
ActionStateSerializable itemSerializable = new SysTextSerializer().Deserialize<ActionStateSerializable>(json) ?? new();
// Создаю модель значения
ActionStateSerializableValue value = new();
// Очищаю списки
Clear(SelectAll);
// Для каждого сообщения
foreach (string messageString in itemSerializable.Messages)
{
// - создаю сообщение
ActionStateMessage message = new();
// - десериализую в него данные из модели
message.Deserialize(messageString);
// - добавляю в список
Add(message);
}
// Десериализую данные значения из модели
value.Deserialize(itemSerializable.Value);
// Получаю значение
Value = value.SetSerializedValue<T>();
}
#endregion
}

View File

@ -6,14 +6,4 @@
/// Обновлено 2023.11.1 /// Обновлено 2023.11.1
/// * Добавлен класс ActionState без возвращаемого значения /// * Добавлен класс ActionState без возвращаемого значения
/// </summary> /// </summary>
public sealed class ActionState: ActionState<string> public sealed class ActionState: ActionState<string> { }
{
/// <summary>
/// Добавляет другое состояние (например, результат другого действия, который возвращает <see cref="ActionState"/>).
/// </summary>
/// <param name="state">Запись состояния</param>
public void AddState (ActionState state)
{
base.AddState(state);
}
}

View File

@ -0,0 +1,49 @@
using anbs_cp.Interfaces;
namespace anbs_cp.Classes;
/// <summary>
/// Класс предупреждения
/// </summary>
public sealed class ActionWarning: IActionWarning
{
#region Конструкторы
/// <summary>
/// Конструктор по умолчанию
/// </summary>
public ActionWarning ()
{
IsInformWarning = false;
Object = string.Empty;
Message = string.Empty;
}
/// <summary>
/// Конструктор
/// </summary>
/// <param name="eObject">Объект</param>
/// <param name="message">Сообщение</param>
/// <param name="isInform">Является ли информирующим предупреждением</param>
public ActionWarning (string eObject, string message, bool isInform = false)
{
IsInformWarning = isInform;
Object = eObject;
Message = message;
}
#endregion
#region Реализация интерфейса
/// <summary>
/// Объект
/// </summary>
public object Object { get; set; }
/// <summary>
/// Сообщение
/// </summary>
public string Message { get; set; }
/// <summary>
/// Информирующее предупреждение возникает для предупреждения ВОЗМОЖНОЙ ошибки в дальнейшей эксплуатации и не влияет на текущую операцию.
/// </summary>
public bool IsInformWarning { get; init; }
#endregion
}

View File

@ -3,50 +3,37 @@
/// <summary> /// <summary>
/// Обработчик параметров консоли /// Обработчик параметров консоли
/// </summary> /// </summary>
/// <param name="consoleParams">Параметры консоли</param> public sealed class ConsoleParamsParser
/// <param name="caseSensitive">Регистрозависимые ли параметры</param>
public sealed class ConsoleParamsParser(IEnumerable<string> consoleParams, bool caseSensitive = true)
{ {
/// <summary> /// <summary>
/// Массив параметров /// Массив параметров
/// </summary> /// </summary>
private readonly KeyValueList<string, string?> _paramsList = ParseConsoleParams(consoleParams, caseSensitive); private readonly List<(string, string?)> _paramsList;
/// <summary> /// <summary>
/// Парсер параметров /// Конструктор
/// </summary> /// </summary>
/// <param name="paramsList">Входящий список параметров</param> /// <param name="consoleParams">Параметры консоли</param>
/// <param name="caseSensitive">Регистрозависимые ли параметры</param> public ConsoleParamsParser (string[] consoleParams)
/// <returns>Список параметров</returns>
private static KeyValueList<string, string?> ParseConsoleParams(IEnumerable<string> paramsList,
bool caseSensitive = true)
{ {
// Создаю список параметров //Создаю список параметров
KeyValueList<string, string?> result = []; _paramsList = new();
// Заполняю его //Заполняю его
foreach (string consoleParam in paramsList) foreach (string consoleParam in consoleParams)
{ {
// Индекс знака "=" //Индекс знака "="
int eqPlace = consoleParam.IndexOf('='); int eqPlace = consoleParam.IndexOf('=');
// Получаю параметр //Получаю параметр
string param = eqPlace > -1 ? consoleParam[..eqPlace] : consoleParam; string param = eqPlace > -1 ? consoleParam[..eqPlace] : consoleParam;
// Проверяю, требуются ли регистрозависимые параметры //Получаю значение параметра
if (!caseSensitive) string? value = eqPlace == -1 ? null : consoleParam[(eqPlace + 1)..].Trim(new[] { '"' });
// - если нет, то переводим в нижний регистр
param = param.ToLower();
// Получаю значение параметра //Сохраняю в списке
string? value = eqPlace == -1 ? null : consoleParam[(eqPlace + 1)..].Trim(['"']); _paramsList.Add((param.ToLower(), value));
// Сохраняю в списке
result.Add(param.ToLower(), value);
} }
// Возвращаю значение
return result;
} }
/// <summary> /// <summary>
@ -54,76 +41,21 @@ public sealed class ConsoleParamsParser(IEnumerable<string> consoleParams, bool
/// </summary> /// </summary>
/// <param name="param">Параметр</param> /// <param name="param">Параметр</param>
/// <returns>Есть ли параметр в списке</returns> /// <returns>Есть ли параметр в списке</returns>
// ReSharper disable once MemberCanBePrivate.Global public bool HasParam (string param) =>
public bool HasParam(string param) _paramsList.Any(keyValue => keyValue.Item1 == param.ToLower());
{
// Проверяю регистрозависимость
if (!caseSensitive)
// - если нет, то переводим в нижний регистр
param = param.ToLower();
// Проверяю наличие параметра
return _paramsList.Any(keyValue => keyValue.Key == param.ToLower());
}
/// <summary> /// <summary>
/// Проверяет наличие параметров /// Получает значение параметра
/// </summary> /// </summary>
/// <param name="params">Массив параметров</param> /// <param name="param"></param>
/// <returns>Задан ли хотя бы один параметр</returns> /// <returns></returns>
public bool HasParams(IEnumerable<string> @params) => public string? GetValue (string param) =>
@params.Aggregate(false, (current, param) => current || HasParam(param)); !HasParam(param) ? null : _paramsList.FirstOrDefault(keyValue => keyValue.Item1 == param.ToLower()).Item2;
/// <summary>
/// Получает значение параметра,
/// </summary>
/// <param name="param">Имя параметра</param>
/// <param name="default">Значение по умолчанию</param>
/// <returns>Значение параметра или значение по умолчанию</returns>
public string GetValue(string param, string @default = "") =>
!HasParam(param)
? @default
: _paramsList.FirstOrDefault(keyValue => keyValue.Key == param.ToLower()).Value ?? @default;
/// <summary>
/// Получает значения параметров из списка.
/// </summary>
/// <param name="params">Список параметров</param>
/// <returns>Список значений параметров</returns>
public IEnumerable<string> GetValue(IEnumerable<string> @params)
{
// Задаю результат
List<string> result = [];
// Получаю список параметров
List<string> paramsList = @params.ToList();
// Проверяю наличие параметров
if (!HasParams(paramsList))
// - если нет, возвращаю значение по умолчанию
return [];
// Для каждого параметра, если задано значение - добавляю его в результат
result.AddRange(paramsList.Where(HasParam).Select(param => GetValue(param))
.Where(value => !string.IsNullOrWhiteSpace(value)));
// Возвращаю результат
return result;
}
/// <summary>
/// Получает значение первого заданного параметра и возвращает значение по умолчанию, если ни один из параметров не задан.
/// </summary>
/// <param name="params">Список параметров</param>
/// <param name="default">Значение по умолчанию</param>
/// <returns>Значение первого заданного параметра из списка или значение по умолчанию</returns>
public string GetValue(IEnumerable<string> @params, string @default) =>
GetValue(@params).FirstOrDefault() ?? @default;
/// <summary> /// <summary>
/// Получает список всех параметров /// Получает список всех параметров
/// </summary> /// </summary>
/// <returns>Список всех параметров</returns> /// <returns>Список всех параметров</returns>
public List<string> GetParamsList() => public List<string> GetParamsList () =>
_paramsList.Select(static keyValue => keyValue.Key.ToLower()).ToList(); _paramsList.Select(static keyValue => keyValue.Item1.ToLower()).ToList();
} }

View File

@ -3,11 +3,19 @@
/// <summary> /// <summary>
/// Конвертер количества элементов /// Конвертер количества элементов
/// </summary> /// </summary>
public sealed class CountConverter (IEnumerable<string> valueNames, byte decimalPlace = 0): ValueConverter( public sealed class CountConverter : ValueConverter
valueNames, 1000, decimalPlace)
{ {
/// <summary> /// <summary>
/// Имена размеров файлов по умолчанию /// Имена размеров файлов по умолчанию
/// </summary> /// </summary>
public static readonly string[] DefaultNames = { "", "тыс.", "млн." }; public static readonly string[] DefaultNames = {"", "тыс.", "млн."};
/// <summary>
/// Конструктор класса
/// </summary>
/// <param name="valueNames">Массив имён размерностей</param>
/// <param name="decimalPlace">Знаков после запятой (0, 1, 2)</param>
public CountConverter (string[] valueNames, byte decimalPlace = 0) : base(valueNames, 1000, decimalPlace)
{
}
} }

View File

@ -30,37 +30,28 @@ public sealed class StringEncryptor: IEncryptor
/// </summary> /// </summary>
/// <param name="value">Строка, которая должна быть зашифрована</param> /// <param name="value">Строка, которая должна быть зашифрована</param>
/// <param name="salt">Ключ</param> /// <param name="salt">Ключ</param>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <returns>Этот метод возвращает зашифрованную строку <paramref name="value"/></returns> /// <returns>Этот метод возвращает зашифрованную строку <paramref name="value"/></returns>
/// <exception cref="FormatException">Ошибка неверного формата</exception> public string Encrypt (string value, string salt)
public string Encrypt (string value, string salt, string valueIfFail = "")
{ {
try // Создаю криптограф
{ using Aes aes = Aes.Create();
// Создаю криптограф
using Aes aes = Aes.Create();
// Получаю ключ // Получаю ключ
aes.Key = KeyFromString(salt, aes.IV); aes.Key = KeyFromString(salt, aes.IV);
// Открываю поток // Открываю поток
using MemoryStream ms = new(); using MemoryStream ms = new();
// Пишу данные в поток // Пишу данные в поток
ms.Write(aes.IV); ms.Write(aes.IV);
// Создаю шифрованный поток // Создаю шифрованный поток
using (CryptoStream cs = new(ms, aes.CreateEncryptor(), CryptoStreamMode.Write, true)) using (CryptoStream cs = new(ms, aes.CreateEncryptor(), CryptoStreamMode.Write, true))
// Пишу данные в него // Пишу данные в него
cs.Write(Encoding.UTF8.GetBytes(value)); cs.Write(Encoding.UTF8.GetBytes(value));
// Возвращаю зашифрованный текст // Возвращаю зашифрованный текст
return Convert.ToBase64String(ms.ToArray()); return Convert.ToBase64String(ms.ToArray());
}
catch (FormatException)
{
return valueIfFail;
}
} }
/// <summary> /// <summary>
@ -68,90 +59,69 @@ public sealed class StringEncryptor: IEncryptor
/// </summary> /// </summary>
/// <param name="encryptedValue">Строка, которая должна быть дешифрована</param> /// <param name="encryptedValue">Строка, которая должна быть дешифрована</param>
/// <param name="salt">Ключ</param> /// <param name="salt">Ключ</param>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <returns>Этот метод возвращает дешифрованную строку <paramref name="encryptedValue"/></returns> /// <returns>Этот метод возвращает дешифрованную строку <paramref name="encryptedValue"/></returns>
/// <exception cref="FormatException">Ошибка неверного формата</exception> public string Decrypt (string encryptedValue, string salt)
public string Decrypt (string encryptedValue, string salt, string valueIfFail = "")
{ {
try // Открываю поток в памяти
{ using MemoryStream ms = new(Convert.FromBase64String(encryptedValue));
// Открываю поток в памяти
using MemoryStream ms = new(Convert.FromBase64String(encryptedValue));
// Задаю ключ // Задаю ключ
byte[] iv = new byte[16]; byte[] iv = new byte[16];
// Читаю его // Читаю его
_ = ms.Read(iv); _ = ms.Read(iv);
// Создаю криптограф // Создаю криптограф
using Aes aes = Aes.Create(); using Aes aes = Aes.Create();
// Получаю ключ // Получаю ключ
aes.Key = KeyFromString(salt, iv); aes.Key = KeyFromString(salt, iv);
// присваиваю ключ // присваиваю ключ
aes.IV = iv; aes.IV = iv;
// Создаю поток дешифратора // Создаю поток дешифратора
using CryptoStream cs = new(ms, aes.CreateDecryptor(), CryptoStreamMode.Read, true); using CryptoStream cs = new(ms, aes.CreateDecryptor(), CryptoStreamMode.Read, true);
// Задаю поток итогового текста // Задаю поток итогового текста
using MemoryStream output = new(); using MemoryStream output = new();
// Копирую данные в выходной поток // Копирую данные в выходной поток
cs.CopyTo(output); cs.CopyTo(output);
// Вывожу расшифрованный текст // Вывожу расшифрованный текст
return Encoding.UTF8.GetString(output.ToArray()); return Encoding.UTF8.GetString(output.ToArray());
}
catch (FormatException)
{
return valueIfFail;
}
} }
/// <summary> /// <summary>
/// Декодирует зашифрованную строку в HTML-пригодный формат /// Декодирует зашифрованную строку в HTML-пригодный формат
/// </summary> /// </summary>
/// <param name="text">Зашифрованная строка</param> /// <param name="text">Зашифрованная строка</param>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <returns>Этот метод возвращает дешифрованную строку <paramref name="text"/></returns> /// <returns>Этот метод возвращает дешифрованную строку <paramref name="text"/></returns>
/// <exception cref="FormatException">Ошибка неверного формата</exception> public string Base64UrlEncode (string text) => text.TrimEnd('=').Replace('+', '-').Replace('/', '_');
public string Base64UrlEncode(string text, string valueIfFail = "") =>
text.TrimEnd('=').Replace('+', '-').Replace('/', '_');
/// <summary> /// <summary>
/// Раскодирует из декодированной строки в HTML-пригодный формат /// Раскодирует из декодированной строки в HTML-пригодный формат
/// </summary> /// </summary>
/// <param name="text">Декодированная строка</param> /// <param name="text">Декодированная строка</param>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <returns>Этот метод возвращает шифрованную строку <paramref name="text"/></returns> /// <returns>Этот метод возвращает шифрованную строку <paramref name="text"/></returns>
/// <exception cref="FormatException">Ошибка неверного формата</exception> public string Base64UrlDecode (string text)
public string Base64UrlDecode (string text, string valueIfFail = "")
{ {
try // Первоначальная замена
{ string result = text.Replace('_', '/').Replace('-', '+');
// Первоначальная замена
string result = text.Replace('_', '/').Replace('-', '+');
// Заменяю значения // Заменяю значения
switch (result.Length % 4) switch (result.Length % 4)
{
case 2:
result += "==";
break;
case 3:
result += "=";
break;
}
// Возвращаю результат
return result;
}
catch (FormatException)
{ {
return valueIfFail; case 2:
result += "==";
break;
case 3:
result += "=";
break;
} }
// Возвращаю результат
return result;
} }
} }

View File

@ -0,0 +1,27 @@
namespace anbs_cp.Classes;
/// <summary>
/// Класс -- расширение для класса File
/// </summary>
public static class FileExtension
{
/// <summary>
/// Получает MIME-тип файла
/// </summary>
/// <param name="filename">Имя файла</param>
/// <returns>MIME-тип файла</returns>
public static string MIMEType (string filename) =>
MimeTypes.GetMimeType(filename);
/// <summary>
/// Размер файла в байтах
/// </summary>
/// <param name="fileName">Полное имя и путь к файлу</param>
/// <returns>Размер файла в байтах</returns>
public static long FileSize(string fileName)
{
FileInfo fileInfo = new (fileName);
return fileInfo.Length;
}
}

View File

@ -24,7 +24,10 @@ public sealed class FileHash
/// <summary> /// <summary>
/// Простой конструктор /// Простой конструктор
/// </summary> /// </summary>
public FileHash () => Hash = []; public FileHash ()
{
Hash = new byte[] { };
}
/// <summary> /// <summary>
/// Хэш файла /// Хэш файла
@ -46,13 +49,4 @@ public sealed class FileHash
UTF8Encoding utf8 = new(); UTF8Encoding utf8 = new();
Hash = utf8.GetBytes(value); Hash = utf8.GetBytes(value);
} }
/// <summary>
/// Сравнивает текущий хэш с хэшем <paramref name="otherHash"/> и выдаёт <see cref="bool.TrueString"/>, если совпадают,
/// и <see cref="bool.FalseString"/>, если не совпадают.
/// </summary>
/// <param name="otherHash">Другой хэш</param>
/// <returns><see cref="bool.TrueString"/>, если совпадают, и <see cref="bool.FalseString"/>, если не совпадают</returns>
public bool IsEqual (FileHash otherHash) =>
string.Equals(ToString(), otherHash.ToString(), StringComparison.OrdinalIgnoreCase);
} }

View File

@ -3,13 +3,19 @@
/// <summary> /// <summary>
/// Конвертер размеров файлов /// Конвертер размеров файлов
/// </summary> /// </summary>
/// <param name="valueNames">Массив имён размерностей</param> public sealed class FileSizeConverter : ValueConverter
/// <param name="decimalPlace">Знаков после запятой (0, 1, 2)</param>
public sealed class FileSizeConverter (IEnumerable<string> valueNames, byte decimalPlace = 2): ValueConverter(
valueNames, 1024, decimalPlace)
{ {
/// <summary> /// <summary>
/// Имена размеров файлов по умолчанию /// Имена размеров файлов по умолчанию
/// </summary> /// </summary>
public static readonly string[] DefaultNames = { "байт", "Кб", "Мб", "Гб", "Тб" }; public static readonly string[] DefaultNames = {"байт", "Кб", "Мб", "Гб", "Тб"};
/// <summary>
/// Конструктор класса
/// </summary>
/// <param name="valueNames">Массив имён размерностей</param>
/// <param name="decimalPlace">Знаков после запятой (0, 1, 2)</param>
public FileSizeConverter (string[] valueNames, byte decimalPlace = 2) : base(valueNames, 1024, decimalPlace)
{
}
} }

View File

@ -1,6 +1,5 @@
using System.Collections; using System.Collections;
using anbs_cp.Interfaces;
using anbs_cp.Structs; using anbs_cp.Structs;
namespace anbs_cp.Classes; namespace anbs_cp.Classes;
@ -10,13 +9,19 @@ namespace anbs_cp.Classes;
/// </summary> /// </summary>
/// <typeparam name="TK">Тип ключа</typeparam> /// <typeparam name="TK">Тип ключа</typeparam>
/// <typeparam name="TV">Тип значения</typeparam> /// <typeparam name="TV">Тип значения</typeparam>
// ReSharper disable once ClassCanBeSealed.Global public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>
public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
{ {
/// <summary> /// <summary>
/// Хранение значений /// Хранение значений
/// </summary> /// </summary>
private readonly List<KeyValue<TK, TV>> _list = []; private readonly List<KeyValue<TK, TV>> _list;
#region Конструкторы
/// <summary>
/// Конструктор по умолчанию
/// </summary>
public KeyValueList () => _list = new();
#endregion
#region Свойства #region Свойства
/// <summary> /// <summary>
@ -26,6 +31,7 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
#endregion #endregion
#region Методы #region Методы
/// <summary> /// <summary>
/// Получает список ключей /// Получает список ключей
/// </summary> /// </summary>
@ -36,47 +42,23 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// Добавляет в список параметр /// Добавляет в список параметр
/// </summary> /// </summary>
/// <param name="keyValue">Параметр</param> /// <param name="keyValue">Параметр</param>
public void Add (KeyValue<TK, TV> keyValue) public void Add (KeyValue<TK, TV> keyValue) => _list.Add(keyValue);
{
// Проверяет, существует ли ключ в списке
if (Contains(keyValue.Key))
ChangeValue(keyValue);
// Добавляем в список
_list.Add(keyValue);
}
/// <summary> /// <summary>
/// Добавляет в список параметр /// Добавляет в список параметр
/// </summary> /// </summary>
/// <param name="key">Ключ параметра</param> /// <param name="key">Ключ параметра</param>
/// <param name="value">Значение</param> /// <param name="value">Значение</param>
public void Add (TK key, TV value) => Add(new(key, value)); public void Add (TK key, TV value) => _list.Add(new(key, value));
/// <summary>
/// Добавляет в список некоторый набор элементов
/// </summary>
/// <param name="list">Некоторый набор элементов</param>
public void AddRange (IEnumerable<KeyValue<TK, TV>> list)
{
// Получаю список
List<KeyValue<TK, TV>> keyValues = list.ToList();
// Для каждого элемента списка
foreach (KeyValue<TK, TV> keyValue in keyValues)
// - добавляю его в список
Add(keyValue);
}
/// <summary> /// <summary>
/// Изменяет значение /// Изменяет значение
/// </summary> /// </summary>
/// <param name="keyValue">Новое значение</param> /// <param name="keyValue">Новое значение</param>
// ReSharper disable once MemberCanBePrivate.Global
public void ChangeValue (KeyValue<TK, TV> keyValue) public void ChangeValue (KeyValue<TK, TV> keyValue)
{ {
// Если такой ключ не существует // Если такой ключ не существует
if (!Contains(keyValue.Key)) if (!Contains(keyValue.Key!))
{ {
// - тогда добавляю новое значение // - тогда добавляю новое значение
Add(keyValue); Add(keyValue);
@ -86,7 +68,7 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
} }
// Существующее значение // Существующее значение
KeyValue<TK, TV> existValue = GetItem(keyValue.Key) ?? new(); KeyValue<TK, TV> existValue = GetItem(keyValue.Key!) ?? new();
// Удаляем существующее // Удаляем существующее
_list.Remove(existValue); _list.Remove(existValue);
@ -107,11 +89,9 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// </summary> /// </summary>
/// <param name="key">Ключ</param> /// <param name="key">Ключ</param>
/// <returns>Элемент <see cref="KeyValue{TK,TV}"/></returns> /// <returns>Элемент <see cref="KeyValue{TK,TV}"/></returns>
// ReSharper disable once MemberCanBePrivate.Global
public KeyValue<TK, TV>? GetItem (TK key) public KeyValue<TK, TV>? GetItem (TK key)
{ {
// Ищем элемент в списке // Ищем элемент в списке
// ReSharper disable once NullableWarningSuppressionIsUsed
foreach (KeyValue<TK, TV> keyValueItem in _list.Where(keyValueItem => keyValueItem.Key!.Equals(key))) foreach (KeyValue<TK, TV> keyValueItem in _list.Where(keyValueItem => keyValueItem.Key!.Equals(key)))
// - возвращаем его при нахождении // - возвращаем его при нахождении
return keyValueItem; return keyValueItem;
@ -143,7 +123,6 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// Удаляет элемент из списка /// Удаляет элемент из списка
/// </summary> /// </summary>
/// <param name="keyValue">Элемент</param> /// <param name="keyValue">Элемент</param>
// ReSharper disable once MemberCanBePrivate.Global
public void Remove (KeyValue<TK, TV> keyValue) => _list.Remove(keyValue); public void Remove (KeyValue<TK, TV> keyValue) => _list.Remove(keyValue);
/// <summary> /// <summary>
@ -157,7 +136,6 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// </summary> /// </summary>
/// <param name="keyValue">Элемент</param> /// <param name="keyValue">Элемент</param>
/// <returns>Результат проверки</returns> /// <returns>Результат проверки</returns>
// ReSharper disable once MemberCanBePrivate.Global
public bool Contains (KeyValue<TK, TV> keyValue) => _list.Contains(keyValue); public bool Contains (KeyValue<TK, TV> keyValue) => _list.Contains(keyValue);
/// <summary> /// <summary>
@ -165,19 +143,8 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// </summary> /// </summary>
/// <param name="key">Ключ элемента</param> /// <param name="key">Ключ элемента</param>
/// <returns>Результат проверки</returns> /// <returns>Результат проверки</returns>
// ReSharper disable once NullableWarningSuppressionIsUsed
// ReSharper disable once MemberCanBePrivate.Global
public bool Contains (TK key) => Keys.Any(keyParam => keyParam!.Equals(key)); public bool Contains (TK key) => Keys.Any(keyParam => keyParam!.Equals(key));
/// <summary>
/// Очистка списка
/// </summary>
public void Clear ()
{
// Очищаю список
_list.Clear();
}
#endregion #endregion
#region Реализация интерфейса IEnumerable<KeyValue<TK, TV>> #region Реализация интерфейса IEnumerable<KeyValue<TK, TV>>
@ -193,42 +160,4 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// <returns><see cref="IEnumerator"/></returns> /// <returns><see cref="IEnumerator"/></returns>
IEnumerator IEnumerable.GetEnumerator () => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator () => GetEnumerator();
#endregion #endregion
#region Реализация интерфейса ISerializable
/// <inheritdoc />
public string Serialize ()
{
// Создаю результат
List<string> result = [];
// Добавляю сериализованные значения
result.AddRange(_list.Select(static item => item.Serialize()));
// Вывожу результат
return new NewtonsoftJsonSerializer().Serialize(result);
}
/// <inheritdoc />
public void Deserialize (string json)
{
// Создаю результат
List<string> result = new NewtonsoftJsonSerializer().Deserialize<List<string>>(json) ?? [];
// Очищаю список
_list.Clear();
// Пробегаю все значения
foreach (string itemString in result)
{
// - создаю новое значение
KeyValue<TK, TV> item = new();
// - десериализую в него элемента
item.Deserialize(itemString);
// - добавляю получившееся в список
_list.Add(item);
}
}
#endregion
} }

View File

@ -1,222 +0,0 @@
using System.Collections;
using anbs_cp.Interfaces;
using anbs_cp.Structs;
namespace anbs_cp.Classes;
/// <summary>
/// Упорядоченный список из пары ключ-значение
/// </summary>
/// <typeparam name="TV">Тип значения</typeparam>
// ReSharper disable once ClassCanBeSealed.Global
public class KeyValueOrderedList<TV>: IEnumerable<KeyValueOrdered<TV>>, ISerializable
{
/// <summary>
/// Хранение значений
/// </summary>
private readonly SortedSet<KeyValueOrdered<TV>> _list = [];
#region Свойства
/// <summary>
/// Список ключей из списка
/// </summary>
public IEnumerable<string> Keys => GetKeys();
#endregion
#region Методы
/// <summary>
/// Получает список ключей
/// </summary>
/// <returns>Список ключей</returns>
private IEnumerable<string> GetKeys () => from keyValue in _list where keyValue.Key is not null select keyValue.Key;
/// <summary>
/// Добавляет в список параметр
/// </summary>
/// <param name="keyValue">Параметр</param>
public void Add (KeyValueOrdered<TV> keyValue)
{
// Проверяет, существует ли ключ в списке
if (Contains(keyValue.Key))
ChangeValue(keyValue);
// Добавляем в список
_list.Add(keyValue);
}
/// <summary>
/// Добавляет в список параметр
/// </summary>
/// <param name="key">Ключ параметра</param>
/// <param name="value">Значение</param>
public void Add (string key, TV value) => Add(new(key, value));
/// <summary>
/// Добавляет в список некоторый набор элементов
/// </summary>
/// <param name="list">Некоторый набор элементов</param>
public void AddRange (IEnumerable<KeyValueOrdered<TV>> list)
{
// Получаю список
List<KeyValueOrdered<TV>> keyValues = list.ToList();
// Для каждого элемента списка
foreach (KeyValueOrdered<TV> keyValue in keyValues)
// - добавляю его в список
Add(keyValue);
}
/// <summary>
/// Изменяет значение
/// </summary>
/// <param name="keyValue">Новое значение</param>
// ReSharper disable once MemberCanBePrivate.Global
public void ChangeValue (KeyValueOrdered<TV> keyValue)
{
// Если такой ключ не существует
if (!Contains(keyValue.Key))
{
// - тогда добавляю новое значение
Add(keyValue);
// - прерываю
return;
}
// Удаляем существующее
_list.RemoveWhere(item => item.Key == keyValue.Key);
// Добавляем новое
_list.Add(keyValue);
}
/// <summary>
/// Изменяет значение
/// </summary>
/// <param name="key">Ключ</param>
/// <param name="newValue">Новое значение</param>
public void ChangeValue (string key, TV newValue) => ChangeValue(new(key, newValue));
/// <summary>
/// Получает элемент по ключу
/// </summary>
/// <param name="key">Ключ</param>
/// <returns>Элемент <see cref="KeyValue{TK,TV}"/></returns>
// ReSharper disable once MemberCanBePrivate.Global
public KeyValueOrdered<TV>? GetItem (string key)
{
// Ищем элемент в списке
foreach (KeyValueOrdered<TV> keyValueItem in _list.Where(item => item.Key == key))
// - возвращаем его при нахождении
return keyValueItem;
// Элемент не найден -- вывожу null
return null;
}
/// <summary>
/// Получает значение
/// </summary>
/// <param name="key">Ключ</param>
/// <returns>Значение</returns>
public TV? GetValue (string key)
{
// Если такой ключ не существует
if (!Contains(key))
// Тогда возвращаю значение по умолчанию
return default;
// Получаю элемент
KeyValueOrdered<TV> keyValue = GetItem(key) ?? new();
// Вывожу значение
return keyValue.Value;
}
/// <summary>
/// Удаляет элемент из списка
/// </summary>
/// <param name="keyValue">Элемент</param>
// ReSharper disable once MemberCanBePrivate.Global
public void Remove (KeyValueOrdered<TV> keyValue) => _list.Remove(keyValue);
/// <summary>
/// Удаляет элемент из списка
/// </summary>
/// <param name="key">Ключ элемента</param>
public void Remove (string key) => Remove(GetItem(key) ?? new());
/// <summary>
/// Проверяет, содержится ли элемент в списке
/// </summary>
/// <param name="keyValue">Элемент</param>
/// <returns>Результат проверки</returns>
// ReSharper disable once MemberCanBePrivate.Global
public bool Contains (KeyValueOrdered<TV> keyValue) => _list.Contains(keyValue);
/// <summary>
/// Проверяет, содержится ли элемент в списке
/// </summary>
/// <param name="key">Ключ элемента</param>
/// <returns>Результат проверки</returns>
// ReSharper disable once NullableWarningSuppressionIsUsed
// ReSharper disable once MemberCanBePrivate.Global
public bool Contains (string key) => Keys.Any(keyName => keyName == key);
/// <summary>
/// Очистка списка
/// </summary>
public void Clear ()
{
// Очищаю список
_list.Clear();
}
#endregion
#region Реализация интерфейса IEnumerable<KeyValue<TK, TV>>
/// <inheritdoc />
public IEnumerator<KeyValueOrdered<TV>> GetEnumerator () => _list.GetEnumerator();
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator () => GetEnumerator();
#endregion
#region Реализация интерфейса ISerializable
/// <inheritdoc />
public string Serialize ()
{
// Создаю результат
List<string> result = [];
// Добавляю сериализованные значения
result.AddRange(_list.Select(static item => item.Serialize()));
// Вывожу результат
return new NewtonsoftJsonSerializer().Serialize(result);
}
/// <inheritdoc />
public void Deserialize (string json)
{
// Создаю результат
List<string> result = new NewtonsoftJsonSerializer().Deserialize<List<string>>(json) ?? [];
// Очищаю список
_list.Clear();
// Пробегаю все значения
foreach (string itemString in result)
{
// - создаю новое значение
KeyValueOrdered<TV> item = new();
// - десериализую в него элемента
item.Deserialize(itemString);
// - добавляю получившееся в список
_list.Add(item);
}
}
#endregion
}

View File

@ -10,20 +10,20 @@ public static class LikeDelphi
{ {
/// <summary> /// <summary>
/// Аналог функции IncludeTrailingBackslash /// Аналог функции IncludeTrailingBackslash
/// версия 2.1 (20240403) - исправлена ошибка;
/// версия 2.0 (20231213) - ОС-независимая реализация.
/// </summary> /// </summary>
/// <param name="path">Путь, к которому нужно добавить slash</param> /// <param name="path">Путь, к которому нужно добавить slash</param>
/// <returns>Путь со slash в конце</returns> /// <returns>Путь со slash в конце</returns>
public static string IncludeTrailingBackslash (string path) public static string IncludeTrailingBackslash (string path)
{ {
// Если path не заканчивается slash-ем //По умолчанию сохраняем путь
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) string result = path;
// - то добавляем slash
path += Path.DirectorySeparatorChar;
// Выводим результат //Если последний символ не "\", то добавим "\" в конце
return path; if (path[^1] != '\\')
result = $@"{path}\";
//Вернём результат
return result;
} }
/// <summary> /// <summary>
@ -32,7 +32,7 @@ public static class LikeDelphi
/// <param name="str">Строка, которую нужно разбить</param> /// <param name="str">Строка, которую нужно разбить</param>
/// <param name="delimiter">Символ-делитель строки</param> /// <param name="delimiter">Символ-делитель строки</param>
/// <returns>Массив строк</returns> /// <returns>Массив строк</returns>
public static List<string> ParseString (string str, char delimiter) => [.. str.Split(delimiter)]; public static List<string> ParseString (string str, char delimiter) => str.Split(delimiter).ToList();
/// <summary> /// <summary>
/// Переименовываю файл /// Переименовываю файл
@ -59,7 +59,7 @@ public static class LikeDelphi
break; break;
//Только для папок (для файлов равносилен RaiseException) //Только для папок (для файлов равносилен RaiseException)
case EOnExistAction.RaiseExceptionIfNotEmpty: case EOnExistAction.RaiseExceptionIfNotEmpty:
throw new RenameException(newName, "Папка уже существует!"); throw new RenameException(newName, "Файл уже существует!");
//Только для папок (для файлов равносилен Abort) //Только для папок (для файлов равносилен Abort)
case EOnExistAction.AbortIfNotEmpty: case EOnExistAction.AbortIfNotEmpty:
return; return;

View File

@ -1,16 +0,0 @@
using anbs_cp.Interfaces;
using Newtonsoft.Json;
namespace anbs_cp.Classes;
/// <inheritdoc />
public class NewtonsoftJsonSerializer: ISerializer
{
/// <inheritdoc />
public string Serialize<T> (T data) => JsonConvert.SerializeObject(data);
/// <inheritdoc />
public T? Deserialize<T>(string json) => JsonConvert.DeserializeObject<T>(json,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
}

View File

@ -1,15 +0,0 @@
using System.Text.Json;
using anbs_cp.Interfaces;
namespace anbs_cp.Classes;
/// <inheritdoc />
public class SysTextSerializer: ISerializer
{
/// <inheritdoc />
public string Serialize<T> (T data) => JsonSerializer.Serialize(data);
/// <inheritdoc />
public T? Deserialize<T> (string json) => JsonSerializer.Deserialize<T>(json);
}

View File

@ -71,13 +71,13 @@ public static class TimestampValidator
/// Проверка временного интервала (в час) /// Проверка временного интервала (в час)
/// </summary> /// </summary>
/// <param name="timestamp">Временной интервал</param> /// <param name="timestamp">Временной интервал</param>
/// <param name="checkedStamp">Проверяемый временной интервал</param> /// <param name="checkedstamp">Проверяемый временной интервал</param>
/// <param name="deltaHour">Временная дельта в часах</param> /// <param name="deltahr">Временная дельта в часах</param>
/// <returns> /// <returns>
/// Попал ли <see cref="checkedStamp" /> в промежуток <paramref name="timestamp" /> + <paramref name="deltaHour" /> /// Попал ли <see cref="checkedstamp" /> в промежуток <paramref name="timestamp" /> + <paramref name="deltahr" />
/// </returns> /// </returns>
public static bool ValidateFromHour(long timestamp, long checkedStamp, ulong deltaHour) => public static bool ValidateFromHour(long timestamp, long checkedstamp, ulong deltahr) =>
Validate(timestamp, checkedStamp, checked(deltaHour * 3600000UL)); Validate(timestamp, checkedstamp, checked(deltahr * 3600000UL));
/// <summary> /// <summary>
/// Проверка попадания текущего времени в заданный интервал (в час) /// Проверка попадания текущего времени в заданный интервал (в час)

View File

@ -1,5 +1,7 @@
using System.Globalization; using System.Globalization;
using Newtonsoft.Json;
namespace anbs_cp.Classes; namespace anbs_cp.Classes;
/// <summary> /// <summary>
@ -71,7 +73,7 @@ public static class TypeConverter
/// <typeparam name="T">Тип</typeparam> /// <typeparam name="T">Тип</typeparam>
/// <param name="value">Значение типа</param> /// <param name="value">Значение типа</param>
/// <returns>Значение в <see cref="string"/></returns> /// <returns>Значение в <see cref="string"/></returns>
public static string TypeToStr<T> (T value) => new SysTextSerializer().Serialize(value); public static string TypeToStr<T> (T value) => JsonConvert.SerializeObject(value);
#endregion #endregion
@ -157,7 +159,7 @@ public static class TypeConverter
/// <param name="defaultValue">Значение по умолчанию</param> /// <param name="defaultValue">Значение по умолчанию</param>
/// <returns>Значение в <see cref="T"/></returns> /// <returns>Значение в <see cref="T"/></returns>
public static T StrToType<T>(string value, T defaultValue) => public static T StrToType<T>(string value, T defaultValue) =>
new SysTextSerializer().Deserialize<T>(value) ?? defaultValue; JsonConvert.DeserializeObject<T>(value) ?? defaultValue;
#endregion #endregion
} }

View File

@ -5,27 +5,36 @@ namespace anbs_cp.Classes;
/// <summary> /// <summary>
/// Абстрактный класс конвертера величин для отображения (улучшенный аналог ValueFormatter) /// Абстрактный класс конвертера величин для отображения (улучшенный аналог ValueFormatter)
/// </summary> /// </summary>
/// <param name="valueNames">Массив имён размерностей</param> public abstract class ValueConverter: IValueConverter
/// <param name="divider">Делитель</param>
/// <param name="decimalPlaces">Число знаков после запятой</param>
public abstract class ValueConverter (IEnumerable<string> valueNames, long divider, byte decimalPlaces): IValueConverter
{ {
#region Реализация интерфейса /// <summary>
/// Конструктор
/// </summary>
/// <param name="valueNames">Массив имён размерностей</param>
/// <param name="divider">Делитель</param>
/// <param name="decimalPlaces">Число знаков после запятой</param>
protected ValueConverter (string[] valueNames, long divider, byte decimalPlaces)
{
ValueNames = valueNames;
Divider = divider;
DecimalPlaces = (byte)(decimalPlaces < 3 ? decimalPlaces : 2);
}
#region Реализация интерфейса
/// <summary> /// <summary>
/// Массив имён размерностей /// Массив имён размерностей
/// </summary> /// </summary>
public string[] ValueNames { get; init; } = valueNames.ToArray(); public string[] ValueNames { get; init; }
/// <summary> /// <summary>
/// Делитель /// Делитель
/// </summary> /// </summary>
public long Divider { get; init; } = divider; public long Divider { get; init; }
/// <summary> /// <summary>
/// Знаков после запятой (0, 1, 2) /// Знаков после запятой (0, 1, 2)
/// </summary> /// </summary>
public byte DecimalPlaces { get; init; } = (byte)(decimalPlaces < 3 ? decimalPlaces : 2); public byte DecimalPlaces { get; init; }
#endregion #endregion
@ -41,8 +50,7 @@ public abstract class ValueConverter (IEnumerable<string> valueNames, long divid
(decimal, int) result = DivideIt(value, 0); (decimal, int) result = DivideIt(value, 0);
//Преобразую значение в строку //Преобразую значение в строку
string resultValue = DecimalPlaces switch string resultValue = DecimalPlaces switch {
{
0 => $"{result.Item1:F0}", 0 => $"{result.Item1:F0}",
1 => $"{result.Item1:F1}", 1 => $"{result.Item1:F1}",
_ => $"{result.Item1:F2}" _ => $"{result.Item1:F2}"
@ -73,7 +81,7 @@ public abstract class ValueConverter (IEnumerable<string> valueNames, long divid
count++; count++;
//... и продолжаем цикл //... и продолжаем цикл
return DivideIt(value / Divider, count); return DivideIt(value / Divider, count);
} }
#endregion #endregion
} }

View File

@ -1,21 +0,0 @@
namespace anbs_cp.Enums;
/// <summary>
/// Тип сообщения о состоянии
/// </summary>
public enum EActionStateMessageType
{ /// <summary>
/// Информация
/// </summary>
Information = 0,
/// <summary>
/// Предупреждение
/// </summary>
Warning = 1,
/// <summary>
/// Ошибка
/// </summary>
Error = 2
}

View File

@ -1,32 +0,0 @@
namespace anbs_cp.Enums;
/// <summary>
/// Область печати состояния действия
/// </summary>
public enum EActionStatePrintArea
{
/// <summary>
/// Все (сообщения, предупреждения, ошибки)
/// </summary>
All = 0,
/// <summary>
/// Только предупреждения и ошибки
/// </summary>
ErrorsAndWarnings = 1,
/// <summary>
/// Только ошибки
/// </summary>
ErrorsOnly = 2,
/// <summary>
/// Только предупреждения
/// </summary>
WarningsOnly = 3,
/// <summary>
/// Только информационные сообщения
/// </summary>
InfosOnly = 4
}

View File

@ -1,17 +0,0 @@
namespace anbs_cp.Enums;
/// <summary>
/// Действие, которое привело к ошибке сериализации
/// </summary>
public enum ESerializeExceptionAction
{
/// <summary>
/// Сериализация
/// </summary>
Serialize = 0,
/// <summary>
/// Десериализация
/// </summary>
Deserialize = 1
}

View File

@ -1,27 +0,0 @@
namespace anbs_cp.Enums;
/// <summary>
/// Трансформация текста
/// </summary>
public enum ETextTransform
{
/// <summary>
/// Как оригинал
/// </summary>
None = 0,
/// <summary>
/// Все буквы строчные (аналог ToLower)
/// </summary>
LowerCase = 1,
/// <summary>
/// Все буквы прописные (аналог ToUpper)
/// </summary>
UpperCase = 2,
/// <summary>
/// Первая буква заглавная, а остальные строчные
/// </summary>
FirstUpper = 3
}

View File

@ -1,28 +0,0 @@
using anbs_cp.Enums;
namespace anbs_cp.Exceptions;
/// <summary>
/// Ошибка (де)сериализации
/// </summary>
/// <param name="action">Действие сериализатора, приведшее к ошибке</param>
/// <param name="objectJson">Объект сериализации при сериализации или строка json при десериализации</param>
/// <param name="message">Сообщение пользователю</param>
public sealed class SerializeException (ESerializeExceptionAction action, string? objectJson, string? message = null)
: Exception(message)
{
/// <summary>
/// Действие сериализатора, приведшее к ошибке
/// </summary>
public ESerializeExceptionAction Action => action;
/// <summary>
/// Объект сериализации (при action == ESerializeExceptionAction.Serialize)
/// </summary>
public string? Object => action == ESerializeExceptionAction.Serialize ? objectJson : null;
/// <summary>
/// Строка json при десериализации
/// </summary>
public string? Json => action == ESerializeExceptionAction.Deserialize ? objectJson : null;
}

View File

@ -1,32 +0,0 @@
namespace anbs_cp.Extensions;
/// <summary>
/// Расширение типа "правда/ложь"
/// </summary>
public static class BooleanExtensions
{
/// <summary>
/// Вывод в строку <paramref name="ifTrue"/>, если выражение <paramref name="b"/> правдиво и
/// <paramref name="ifFalse"/> в противном случае.
/// </summary>
/// <param name="b">Выражение типа правда/ложь</param>
/// <param name="ifTrue">Строка для правдивого выражения</param>
/// <param name="ifFalse">Строка для лживого выражения</param>
/// <returns>Вывод строки</returns>
public static string ExportToString (this bool b, string ifTrue, string ifFalse) => b ? ifTrue : ifFalse;
/// <summary>
/// Вычисляет количество булевых переменных <paramref name="expressions"/> в значении true.
/// </summary>
/// <param name="expressions">Переменные</param>
/// <returns>Количество переменных в значении true</returns>
public static int TrueCount (params bool[] expressions) => expressions.Count(static b => b);
/// <summary>
/// Вычисляет, есть ли хотя бы одно из булевых переменных <paramref name="expressions"/> в значении true.
/// </summary>
/// <param name="expressions">Переменные</param>
/// <returns>Есть ли хотя бы одно в значении true</returns>
public static bool AnyTrue (params bool[] expressions) => TrueCount(expressions) > 0;
}

View File

@ -1,15 +0,0 @@
namespace anbs_cp.Extensions;
/// <summary>
/// Расширение класса DateTime
/// </summary>
public static class DateTimeExtension
{
/// <summary>
/// "Обнуляет" миллисекунды
/// </summary>
/// <param name="dt">Дата/время</param>
/// <returns>Дата/время с нулевыми миллисекундами</returns>
public static DateTime TrimMilliseconds (this DateTime dt) =>
new(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, 0, dt.Kind);
}

View File

@ -1,15 +0,0 @@
using System.Text;
namespace anbs_cp.Extensions;
/// <summary>
/// Класс-расширение для Encoding
/// </summary>
public static class EncodingExtensions
{
/// <summary>
/// Кодировка UTF8 без Bom
/// </summary>
// ReSharper disable once InconsistentNaming
public static Encoding UTF8WithoutBom (this Encoding encoding) => new UTF8Encoding(false);
}

View File

@ -1,172 +0,0 @@
// ReSharper disable MemberCanBePrivate.Global
using anbs_cp.Classes;
using System.Text;
namespace anbs_cp.Extensions;
/// <summary>
/// Класс -- расширение для класса File
/// </summary>
public static class FileExtension
{
/// <summary>
/// Получает MIME-тип файла
/// </summary>
/// <param name="filename">Имя файла</param>
/// <returns>MIME-тип файла</returns>
public static string MimeType (string filename) =>
MimeTypes.GetMimeType(filename);
/// <summary>
/// Размер файла в байтах
/// </summary>
/// <param name="fileName">Полное имя и путь к файлу</param>
/// <returns>Размер файла в байтах</returns>
public static long FileSize (string fileName) =>
new FileInfo(fileName).Length;
/// <summary>
/// Получает хэш файла
/// </summary>
/// <param name="fileName">Имя файла</param>
/// <returns>Хэш файла в формате <see cref="FileHash"/></returns>
public static FileHash GetHash (string fileName) =>
new(fileName);
/// <summary>
/// Получение содержимого файла
/// </summary>
/// <param name="fileName">Имя файла</param>
/// <returns>Содержимое файла</returns>
public static byte[] GetFileContent (string fileName) => File.ReadAllBytes(fileName);
#region Write
/// <summary>
/// Записывает данные <paramref name="data"/> в текстовый файл <paramref name="fileName"/>
/// </summary>
/// <typeparam name="T">Тип данных</typeparam>
/// <param name="data">Данные</param>
/// <param name="fileName">Имя файла</param>
/// <param name="encoding">Кодировка</param>
public static void Write<T> (T data, string fileName, Encoding encoding)
{
// Открываю файл для создания или перезаписи
using StreamWriter writer = new(new FileStream(fileName, FileMode.OpenOrCreate), encoding);
// Записываю
writer.WriteLine(new NewtonsoftJsonSerializer().Serialize(data));
}
/// <summary>
/// Записывает данные <paramref name="data"/> в текстовый файл <paramref name="fileName"/>
/// </summary>
/// <typeparam name="T">Тип данных</typeparam>
/// <param name="data">Данные</param>
/// <param name="fileName">Имя файла</param>
/// <param name="useUtf8WithBom">Нужно ли использовать кодировку UTF8 With BOM или UTF8 Without BOM</param>
public static void Write<T> (T data, string fileName, bool useUtf8WithBom = false) => Write(data, fileName,
useUtf8WithBom ? Encoding.UTF8 : Encoding.UTF8.UTF8WithoutBom());
/// <summary>
/// Записывает все данные из списка <paramref name="data"/> в текстовый файл <paramref name="fileName"/>
/// </summary>
/// <param name="data">Данные</param>
/// <param name="fileName">Имя файла</param>
/// <param name="encoding">Кодировка файла</param>
/// <typeparam name="T">Тип данных</typeparam>
public static void WriteAll<T> (IEnumerable<T> data, string fileName, Encoding encoding)
{
// Открываю файл для создания или перезаписи
using StreamWriter writer = new(new FileStream(fileName, FileMode.OpenOrCreate), encoding);
// Для каждого элемента списка
foreach (T element in data)
// - записываю его строкой в файл
writer.WriteLine(new NewtonsoftJsonSerializer().Serialize(element));
}
/// <summary>
/// Записывает все данные из списка <paramref name="data"/> в текстовый файл <paramref name="fileName"/>
/// </summary>
/// <param name="data">Данные</param>
/// <param name="fileName">Имя файла</param>
/// <param name="useUtf8WithBom">Нужно ли использовать кодировку UTF8 With BOM или UTF8 Without BOM</param>
/// <typeparam name="T">Тип данных</typeparam>
public static void WriteAll<T> (IEnumerable<T> data, string fileName, bool useUtf8WithBom = false) =>
WriteAll(data, fileName, useUtf8WithBom ? Encoding.UTF8 : Encoding.UTF8.UTF8WithoutBom());
#endregion
#region Read
/// <summary>
/// Читает первую строку из текстового файла <paramref name="fileName"/>
/// </summary>
/// <param name="fileName">Имя файла</param>
/// <param name="encoding">Кодировка файла</param>
/// <typeparam name="T">Тип выходных данных</typeparam>
/// <returns>Данные или null</returns>
public static T? Read<T> (string fileName, Encoding encoding)
{
// Открываю файл для чтения
using StreamReader reader = new(new FileStream(fileName, FileMode.Open), encoding);
// Считываю первую запись
string serialized = reader.ReadLine() ?? "{}";
// Возвращаю конвертированный тип
return new NewtonsoftJsonSerializer().Deserialize<T>(serialized);
}
/// <summary>
/// Читает первую строку из текстового файла <paramref name="fileName"/>
/// </summary>
/// <param name="fileName">Имя файла</param>
/// <param name="useUtf8WithBom">Нужно ли использовать кодировку UTF8 With BOM или UTF8 Without BOM</param>
/// <typeparam name="T">Тип выходных данных</typeparam>
/// <returns>Данные или null</returns>
public static T? Read<T> (string fileName, bool useUtf8WithBom = false) => Read<T>(fileName,
useUtf8WithBom ? Encoding.UTF8 : Encoding.UTF8.UTF8WithoutBom());
/// <summary>
/// Читает все строки из текстового файла <paramref name="fileName"/>
/// </summary>
/// <param name="fileName">Имя файла</param>
/// <param name="encoding">Кодировка файла</param>
/// <typeparam name="T">Тип выходных данных</typeparam>
/// <returns>Список данных</returns>
public static IEnumerable<T> ReadAll<T> (string fileName, Encoding encoding)
{
// Создаю результат
List<T> result = [];
// Открываю файл для чтения
using StreamReader reader = new(new FileStream(fileName, FileMode.Open), encoding);
// Пока есть строки в файле
while (reader.ReadLine() is { } serialized)
{
// - десериализую их
T? data = new NewtonsoftJsonSerializer().Deserialize<T>(serialized);
// - и если они не нулевые
if (data is not null)
// -- то добавляю их в результат
result.Add(data);
}
// Возвращаю полученный список
return result.AsEnumerable();
}
/// <summary>
/// Читает все строки из текстового файла <paramref name="fileName"/>
/// </summary>
/// <param name="fileName">Имя файла</param>
/// <param name="useUtf8WithBom">Нужно ли использовать кодировку UTF8 With BOM или UTF8 Without BOM</param>
/// <typeparam name="T">Тип выходных данных</typeparam>
/// <returns>Список данных</returns>
public static IEnumerable<T> ReadAll<T> (string fileName, bool useUtf8WithBom = false) =>
ReadAll<T>(fileName, useUtf8WithBom ? Encoding.UTF8 : Encoding.UTF8.UTF8WithoutBom());
#endregion
}

View File

@ -1,69 +0,0 @@
using System.Diagnostics.CodeAnalysis;
namespace anbs_cp.Extensions;
/// <summary>
/// Расширение Guid
/// </summary>
public static class GuidExtensions
{
/// <summary>
/// Проверяет Guid на пустоту
/// </summary>
/// <param name="g">Guid или null</param>
/// <returns>Guid пуст (null) или равен Guid.Empty</returns>
public static bool IsNullOrEmpty ([NotNullWhen(false)] this Guid? g) => g == null || g == Guid.Empty;
/// <summary>
/// Проверяет Guid на пустоту
/// </summary>
/// <param name="g">Guid</param>
/// <returns>Guid пуст (null) или равен Guid.Empty</returns>
public static bool IsNullOrEmpty (this Guid g) => g == Guid.Empty;
/// <summary>
/// Генерирует <see cref="Guid"/>, удовлетворяющий условию <paramref name="predicate"/>
/// </summary>
/// <param name="predicate">Условие генерации <see cref="Guid"/></param>
/// <returns>Новый <see cref="Guid"/></returns>
public static Guid GenerateGuid (Func<Guid, bool> predicate)
{
// Задаю GUID
Guid guid;
// Выполняй
do
{
// - генерируй GUID
guid = Guid.NewGuid();
}
// - пока не выполнено условие
while (!predicate(guid));
// Возвращаю сгенерированный GUID
return guid;
}
/// <summary>
/// Генерирует <see cref="Guid"/>, удовлетворяющий условию <paramref name="asyncPredicate"/>
/// </summary>
/// <param name="asyncPredicate">Условие генерации <see cref="Guid"/></param>
/// <returns>Новый <see cref="Guid"/></returns>
public static async Task<Guid> GenerateGuidAsync (Func<Guid, Task<bool>> asyncPredicate)
{
// Задаю GUID
Guid guid;
// Выполняй
do
{
// - генерируй GUID
guid = Guid.NewGuid();
}
// - пока не выполнено условие
while (!await asyncPredicate(guid));
// Возвращаю сгенерированный GUID
return guid;
}
}

View File

@ -1,83 +0,0 @@
using System.Text;
namespace anbs_cp.Extensions;
/// <summary>
/// Класс-расширение для List
/// </summary>
public static class ListExtensions
{
/// <summary>
/// Загрузка строк из текстового файла
/// </summary>
/// <param name="list">Список, в который нужно загрузит</param>
/// <param name="fileName">Имя файла, который нужно загрузить</param>
/// <param name="useUtf8WithBom">Использовать кодировку UTF8 With Bom</param>
public static void LoadFromFile (this List<string> list, string fileName, bool useUtf8WithBom = false)
{
// Очищаю список
list.Clear();
// Кодировка
Encoding fileEncoding =
useUtf8WithBom ? Encoding.UTF8 : Encoding.UTF8.UTF8WithoutBom();
// Открываю файл для чтения
using StreamReader reader = new(new FileStream(fileName, FileMode.Open), fileEncoding);
// Пока есть строки в файле
while (reader.ReadLine() is { } line)
// - добавляю в список
list.Add(line);
}
/// <summary>
/// Загрузка строк из типизированного файла
/// </summary>
/// <typeparam name="T">Тип данных</typeparam>
/// <param name="list">Список, в который нужно загрузит</param>
/// <param name="fileName">Имя файла, который нужно загрузить</param>
/// <param name="encoding">Кодировка файла</param>
public static void LoadFromFile<T> (this List<T> list, string fileName, Encoding encoding)
{
// Очищаю список
list.Clear();
// Добавляю в список загруженные строки
list.AddRange(FileExtension.ReadAll<T>(fileName, encoding));
}
/// <summary>
/// Сохранение списка строк в файл
/// </summary>
/// <param name="list">Список</param>
/// <param name="fileName">Имя файла</param>
/// <param name="useUtf8WithBom">Использовать кодировку UTF8 With Bom</param>
public static void SaveToFile (this List<string> list, string fileName, bool useUtf8WithBom = false)
{
// Очищаю список
list.Clear();
// Кодировка
Encoding fileEncoding =
useUtf8WithBom ? Encoding.UTF8 : Encoding.UTF8.UTF8WithoutBom();
// Открываю файл для создания или перезаписи
using StreamWriter writer = new(new FileStream(fileName, FileMode.OpenOrCreate), fileEncoding);
// Для каждой строки
foreach (string line in list)
// - записываю её
writer.WriteLine(line);
}
/// <summary>
/// Сохранение списка строк в файл
/// </summary>
/// <typeparam name="T">Тип данных</typeparam>
/// <param name="list">Список</param>
/// <param name="fileName">Имя файла</param>
/// <param name="encoding">Кодировка файла</param>
public static void SaveToFile<T> (this List<T> list, string fileName, Encoding encoding) =>
FileExtension.WriteAll(list.AsEnumerable(), fileName, encoding);
}

View File

@ -1,16 +0,0 @@
using System.Reflection;
namespace anbs_cp.Extensions;
/// <summary>
/// Расширение MethodInfo
/// </summary>
public static class MethodInfoExtension
{
/// <summary>
/// Проверяет, является ли метод асинхронным
/// </summary>
/// <param name="method">Метод</param>
/// <returns>Асинхронный или нет</returns>
public static bool IsAsync (this MethodInfo method) => typeof(Task) == method.ReturnType;
}

View File

@ -1,93 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using anbs_cp.Classes;
using anbs_cp.Enums;
namespace anbs_cp.Extensions;
/// <summary>
/// Расширение строк
/// </summary>
public static class StringExtensions
{
/// <summary>
/// Проверяет строку на пустоту
/// </summary>
/// <param name="s">Строка</param>
/// <returns>Строка пуста (null) или содержит только пробелы</returns>
public static bool IsNullOrWhiteSpace ([NotNullWhen(false)] this string? s) => s == null || s.Trim().Length == 0;
/// <summary>
/// Преобразует текстовое имя параметра перечисления <see cref="T"/> в элемент перечисления.
/// Если такой элемент не найден или при ошибке перевода вернётся элемент по умолчанию <paramref name="defaultValue"/>.
/// </summary>
/// <param name="s">Строка</param>
/// <param name="defaultValue">Значение по умолчанию</param>
/// <typeparam name="T">Тип перечисления</typeparam>
/// <returns>Элемент перечисления <see cref="T"/></returns>
public static T ParseToEnum<T> (this string s, T defaultValue)
{
try
{
return (T)Enum.Parse(typeof(T), s, true);
}
catch (ArgumentException)
{
return defaultValue;
}
}
/// <summary>
/// Приводит строку <paramref name="s"/> к виду "Первая буква заглавная, а все остальные -- строчные"
/// </summary>
/// <param name="s">Строка для перевода</param>
/// <returns>Приведённая строка</returns>
public static string ToFirstUpperCase (this string s)
{
// Если строка пуста
if (s.IsNullOrWhiteSpace())
// - то возвращаю её
return s;
// Задаю результат и устанавливаю первую букву заглавной
string result = $"{s[0]}".ToUpper();
// Если длина s больше, чем 1 символ
if (s.Length > 1)
// - то добавляю в результат оставшиеся символы, приведя их к LowerCase
result += s[1..].ToLower();
// Вывожу результат
return result;
}
/// <summary>
/// Трансформация текста <paramref name="s"/> по правилам <paramref name="type"/>
/// </summary>
/// <param name="s">Текст</param>
/// <param name="type">Правила преобразования</param>
/// <returns>Преобразованный текст</returns>
public static string Transform (this string s, ETextTransform type) =>
type switch
{
ETextTransform.None => s,
ETextTransform.LowerCase => s.ToLower(),
ETextTransform.UpperCase => s.ToUpper(),
ETextTransform.FirstUpper => s.ToFirstUpperCase(),
var _ => s
};
/// <summary>
/// Форматирует строку <paramref name="s"/>, заменяя все совпадения
/// по ключам из <paramref name="replaceList"/> соответствующими значениями из <paramref name="replaceList"/>.
/// Т.е. например, исходная строка «Мой дядя #Name был самых честных правил», массив замен содержал строку
/// «#Name» => «Юра», в итоге будет «Мой дядя Юра был самых честных правил».
/// </summary>
/// <param name="s">Строка для замены</param>
/// <param name="replaceList">Список замен</param>
/// <param name="comparisonType">Региональные параметры, регистр и правила сортировки</param>
/// <returns>Заменённая строка</returns>
public static string Format (this string s, KeyValueOrderedList<string> replaceList,
StringComparison comparisonType = StringComparison.CurrentCulture) => replaceList.Aggregate(s,
(current, replaceItem) => current.Replace(replaceItem.Key, replaceItem.Value, comparisonType));
}

View File

@ -0,0 +1,14 @@
namespace anbs_cp.Interfaces;
/// <summary>
/// Интерфейс ошибки
/// </summary>
public interface IActionError : IActionStateMessage
{
/// <summary>
/// Критичность ошибки:
/// при некритичных ошибках продолжение выполнения операции возможно,
/// а при критичных -- нет
/// </summary>
public bool IsCritical { get; init; }
}

View File

@ -0,0 +1,12 @@
namespace anbs_cp.Interfaces;
/// <summary>
/// Интерфейс для информации по статусу
/// </summary>
public interface IActionInfo : IActionStateMessage
{
/// <summary>
/// Статусная информация (например, начало работы)
/// </summary>
public bool IsStatusInfo { get; init; }
}

View File

@ -0,0 +1,24 @@
namespace anbs_cp.Interfaces;
/// <summary>
/// Интерфейс сообщения состояния
/// </summary>
public interface IActionStateMessage
{
/// <summary>
/// Объект сообщения
/// </summary>
public object Object { get; set; }
/// <summary>
/// Текст сообщения
/// </summary>
public string Message { get; set; }
/// <summary>
/// Функция вывода сообщения
/// </summary>
/// <param name="format">Строка-форматирование (например, «[{0}] - {1}»)</param>
/// <returns>Отформатированную строка</returns>
public string PrintMessage (string format) => string.Format (format, Object, Message);
}

View File

@ -0,0 +1,12 @@
namespace anbs_cp.Interfaces;
/// <summary>
/// Интерфейс предупреждения
/// </summary>
public interface IActionWarning : IActionStateMessage
{
/// <summary>
/// Информирующее предупреждение возникает для предупреждения ВОЗМОЖНОЙ ошибки в дальнейшей эксплуатации и не влияет на текущую операцию.
/// </summary>
public bool IsInformWarning { get; init; }
}

View File

@ -10,32 +10,28 @@ public interface IEncryptor
/// </summary> /// </summary>
/// <param name="value">Строка, которая должна быть зашифрована</param> /// <param name="value">Строка, которая должна быть зашифрована</param>
/// <param name="salt">Ключ шифрования</param> /// <param name="salt">Ключ шифрования</param>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <returns>Этот метод возвращает зашифрованную строку <paramref name="value"/></returns> /// <returns>Этот метод возвращает зашифрованную строку <paramref name="value"/></returns>
string Encrypt (string value, string salt, string valueIfFail); string Encrypt (string value, string salt);
/// <summary> /// <summary>
/// Метод для дешифрования строки <paramref name="encryptedValue"/> /// Метод для дешифрования строки <paramref name="encryptedValue"/>
/// </summary> /// </summary>
/// <param name="encryptedValue">Строка, которая должна быть дешифрована</param> /// <param name="encryptedValue">Строка, которая должна быть дешифрована</param>
/// <param name="salt">Ключ шифрования</param> /// <param name="salt">Ключ шифрования</param>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <returns>Этот метод возвращает дешифрованную строку <paramref name="encryptedValue"/></returns> /// <returns>Этот метод возвращает дешифрованную строку <paramref name="encryptedValue"/></returns>
string Decrypt (string encryptedValue, string salt, string valueIfFail); string Decrypt (string encryptedValue, string salt);
/// <summary> /// <summary>
/// Декодирует зашифрованную строку в HTML-пригодный формат /// Декодирует зашифрованную строку в HTML-пригодный формат
/// </summary> /// </summary>
/// <param name="text">Зашифрованная строка</param> /// <param name="text">Зашифрованная строка</param>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <returns>Этот метод возвращает дешифрованную строку <paramref name="text"/></returns> /// <returns>Этот метод возвращает дешифрованную строку <paramref name="text"/></returns>
string Base64UrlEncode (string text, string valueIfFail); string Base64UrlEncode (string text);
/// <summary> /// <summary>
/// Раскодирует из декодированной строки в HTML-пригодный формат /// Раскодирует из декодированной строки в HTML-пригодный формат
/// </summary> /// </summary>
/// <param name="text">Декодированная строка</param> /// <param name="text">Декодированная строка</param>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <returns>Этот метод возвращает шифрованную строку <paramref name="text"/></returns> /// <returns>Этот метод возвращает шифрованную строку <paramref name="text"/></returns>
string Base64UrlDecode (string text, string valueIfFail); string Base64UrlDecode (string text);
} }

View File

@ -1,23 +0,0 @@
using anbs_cp.Exceptions;
namespace anbs_cp.Interfaces;
/// <summary>
/// Интерфейс для сериализации объектов
/// </summary>
public interface ISerializable
{
/// <summary>
/// Сериализовать элемент в формат json
/// </summary>
/// <returns>Строка в формате json</returns>
/// <exception cref="SerializeException">Ошибка при сериализации</exception>
string Serialize();
/// <summary>
/// Восстановить элемент из формата json
/// </summary>
/// <param name="json">Строка в формате json</param>
/// <exception cref="SerializeException">Ошибка при десериализации</exception>
void Deserialize(string json);
}

View File

@ -1,23 +0,0 @@
namespace anbs_cp.Interfaces;
/// <summary>
/// Сериализация моделей, классов и других объектов
/// </summary>
public interface ISerializer
{
/// <summary>
/// Сериализация данных <paramref name="data"/> в строку.
/// </summary>
/// <typeparam name="T">Тип данных</typeparam>
/// <param name="data">Данные</param>
/// <returns>Сериализованные данные</returns>
string Serialize<T> (T data);
/// <summary>
/// Десериализация данных из json-строки <paramref name="json"/>
/// </summary>
/// <typeparam name="T">Ожидаемый тип данных</typeparam>
/// <param name="json">Сериализованные данные</param>
/// <returns>Данные</returns>
T? Deserialize<T> (string json);
}

View File

@ -65,7 +65,6 @@ public interface IValueFormatter
for (int i = 0; i <= DecimalPlaces; i++) delim *= 10; for (int i = 0; i <= DecimalPlaces; i++) delim *= 10;
// ReSharper disable once PossibleLossOfFraction
decimal value = Math.Round((decimal)(dividend * delim / divider)) / delim; decimal value = Math.Round((decimal)(dividend * delim / divider)) / delim;
return $"{value}"; return $"{value}";

View File

@ -1,88 +1,51 @@
using anbs_cp.Classes; namespace anbs_cp.Structs;
using anbs_cp.Enums;
using anbs_cp.Exceptions;
using anbs_cp.Interfaces;
namespace anbs_cp.Structs;
/// <summary> /// <summary>
/// Пара ключ-значение /// Пара ключ-значение
/// </summary> /// </summary>
/// <typeparam name="TK">Тип ключа</typeparam> /// <typeparam name="TK">Тип ключа</typeparam>
/// <typeparam name="TV">Тип значения</typeparam> /// <typeparam name="TV">Тип значения</typeparam>
/// <param name="Key">Ключ</param> public struct KeyValue<TK, TV>
/// <param name="Value">Значение</param>
public record struct KeyValue<TK, TV> (TK Key, TV? Value): ISerializable
{ {
#region Свойства #region Конструкторы
/// <summary>
/// Конструктор по умолчанию
/// </summary>
public KeyValue ()
{
Key = default;
Value = default;
}
/// <summary>
/// Конструктор со значениями
/// </summary>
/// <param name="key">Ключ</param>
/// <param name="value">Значение</param>
public KeyValue (TK key, TV value)
{
Key = key;
Value = value;
}
#endregion
#region Свойства
/// <summary> /// <summary>
/// Ключ /// Ключ
/// </summary> /// </summary>
public TK Key { get; private set; } = Key; public TK? Key { get; set; }
/// <summary> /// <summary>
/// Значение /// Значение
/// </summary> /// </summary>
// ReSharper disable once MemberCanBePrivate.Global public TV? Value { get; set; }
public TV? Value { get; set; } = Value;
#endregion #endregion
#region Методы #region Методы
/// <summary> /// <summary>
/// Получает ключ-значение по умолчанию /// Получает ключ-значение по умолчанию
/// </summary> /// </summary>
/// <returns>Ключ-значение по умолчанию</returns> /// <returns>Ключ-значение по умолчанию</returns>
public static KeyValue<TK, TV> GetDefault () => new(); public static KeyValue<TK, TV> GetDefault() => new();
#endregion
#region Реализация интерфейса ISerializable
/// <inheritdoc />
public readonly string Serialize ()
{
// Получаю serialized-значение ключа
string keySerialized = new NewtonsoftJsonSerializer().Serialize(Key);
// Исключаю из этого значения = (заменяя на %EQ%)
keySerialized = keySerialized.Replace("=", "%EQ%");
// Получаю serialized-значение значения
string valueSerialized = new NewtonsoftJsonSerializer().Serialize(Value);
// Исключаю из этого значения = (заменяя на %EQ%)
valueSerialized = valueSerialized.Replace("=", "%EQ%");
// Вывожу результат
return $"{keySerialized}={valueSerialized}";
}
/// <inheritdoc />
public void Deserialize (string json)
{
// Разделяю сериализованную строку вида КЛЮЧ=ЗНАЧЕНИЕ на ключ и значение
string[] splited = json.Split('=');
// Проверяю количество частей (должно быть 2)
if (splited.Length != 2)
throw new SerializeException(ESerializeExceptionAction.Deserialize, json,
"Неверное количество частей! Наверное, лишнее =?");
// Получаю сериализованное представление ключа
string keySerialized = splited[0].Replace("%EQ%", "=");
// Получаю сериализованное представление значения
string valueSerialized = splited[1].Replace("%EQ%", "=");
// Десериализую ключ
Key = (new NewtonsoftJsonSerializer().Deserialize<TK>(keySerialized) ?? default(TK))!;
// Десериализую значение
Value = new NewtonsoftJsonSerializer().Deserialize<TV>(valueSerialized);
}
#endregion #endregion
} }

View File

@ -1,106 +0,0 @@
using anbs_cp.Classes;
using anbs_cp.Enums;
using anbs_cp.Exceptions;
using anbs_cp.Interfaces;
namespace anbs_cp.Structs;
/// <summary>
/// Упорядоченная пара ключ-значение
/// </summary>
/// <typeparam name="TValue">Тип значения</typeparam>
/// <param name="key">Ключ</param>
/// <param name="value">Значение</param>
public struct KeyValueOrdered<TValue> (string key, TValue? value): ISerializable, IComparable<KeyValueOrdered<TValue>>
{
#region Свойства
/// <summary>
/// Ключ
/// </summary>
public string Key { get; private set; } = key;
/// <summary>
/// Значение
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
public TValue? Value { get; set; } = value;
#endregion
#region Методы
/// <summary>
/// Получает ключ-значение по умолчанию
/// </summary>
/// <returns>Ключ-значение по умолчанию</returns>
public static KeyValueOrdered<TValue> GetDefault () => new();
#endregion
#region Конвертация в KeyValue<TKey, TValue>
/// <summary>
/// Переводит тип <see cref="KeyValueOrdered{TValue}"/> в тип <see cref="KeyValue{TK,TV}"/>
/// </summary>
/// <param name="keyValue">Тип <see cref="KeyValueOrdered{TValue}"/></param>
/// <returns>Тип <see cref="KeyValue{TK,TV}"/></returns>
public static KeyValue<string, TValue> ToKeyValue (KeyValueOrdered<TValue> keyValue) =>
new(keyValue.Key, keyValue.Value);
/// <summary>
/// Переводит тип <see cref="KeyValue{TK,TV}"/> в тип <see cref="KeyValueOrdered{TValue}"/>
/// </summary>
/// <param name="keyValue">Тип <see cref="KeyValue{TK,TV}"/></param>
/// <returns>Тип <see cref="KeyValueOrdered{TValue}"/></returns>
public static KeyValueOrdered<TValue> ToOrderedKeyValue (KeyValue<string, TValue> keyValue) =>
new(keyValue.Key, keyValue.Value);
#endregion
#region Реализация интерфейса ISerializable
/// <inheritdoc />
public readonly string Serialize ()
{
// Получаю serialized-значение ключа
string keySerialized = Key;
// Исключаю из этого значения = (заменяя на %EQ%)
keySerialized = keySerialized.Replace("=", "%EQ%");
// Получаю serialized-значение значения
string valueSerialized = new NewtonsoftJsonSerializer().Serialize(Value);
// Исключаю из этого значения = (заменяя на %EQ%)
valueSerialized = valueSerialized.Replace("=", "%EQ%");
// Вывожу результат
return $"{keySerialized}={valueSerialized}";
}
/// <inheritdoc />
public void Deserialize (string json)
{
// Разделяю сериализованную строку вида КЛЮЧ=ЗНАЧЕНИЕ на ключ и значение
string[] splited = json.Split('=');
// Проверяю количество частей (должно быть 2)
if (splited.Length != 2)
throw new SerializeException(ESerializeExceptionAction.Deserialize, json,
"Неверное количество частей! Наверное, лишнее =?");
// Получаю сериализованное представление ключа
string keySerialized = splited[0].Replace("%EQ%", "=");
// Получаю сериализованное представление значения
string valueSerialized = splited[1].Replace("%EQ%", "=");
// Десериализую ключ
Key = keySerialized;
// Десериализую значение
Value = new NewtonsoftJsonSerializer().Deserialize<TValue>(valueSerialized);
}
#endregion
#region Реализация интерфейса IComparable<KeyValueOrdered<TValue>>
/// <inheritdoc />
public int CompareTo (KeyValueOrdered<TValue> other) =>
// ReSharper disable once SuspiciousTypeConversion.Global
string.Compare(Key, other.Key, StringComparison.CurrentCultureIgnoreCase);
#endregion
}

View File

@ -1,25 +1,42 @@
using anbs_cp.Classes; namespace anbs_cp.Structs;
using anbs_cp.Interfaces;
namespace anbs_cp.Structs;
/// <summary> /// <summary>
/// Двумерный размер /// Двумерный размер
/// </summary> /// </summary>
/// <param name="width">Длина</param> public struct TwoDimSize
/// <param name="height">Высота</param>
public struct TwoDimSize (int width = 0, int height = 0): ISerializable
{ {
#region Приватные поля #region Приватные поля
/// <summary> /// <summary>
/// Длина (приватное) /// Длина (приватное)
/// </summary> /// </summary>
private int _pWidth = width; private int _pWidth;
/// <summary> /// <summary>
/// Ширина (приватное) /// Высота (приватное)
/// </summary> /// </summary>
private int _pHeight = height; private int _pHeight;
#endregion
#region Конструкторы
/// <summary>
/// Конструктор по умолчанию
/// </summary>
public TwoDimSize ()
{
Width = 0;
Height = 0;
}
/// <summary>
/// Конструктор
/// </summary>
/// <param name="width">Длина</param>
/// <param name="height">Высота</param>
public TwoDimSize (int width, int height)
{
Width = width;
Height = height;
}
#endregion #endregion
#region Свойства #region Свойства
@ -33,7 +50,7 @@ public struct TwoDimSize (int width = 0, int height = 0): ISerializable
} }
/// <summary> /// <summary>
/// Ширина /// Высота
/// </summary> /// </summary>
public int Height public int Height
{ {
@ -41,70 +58,4 @@ public struct TwoDimSize (int width = 0, int height = 0): ISerializable
set => _pHeight = value < 0 ? 0 : value; set => _pHeight = value < 0 ? 0 : value;
} }
#endregion #endregion
#region Методы
/// <summary>
/// Конвертация в строку
/// </summary>
/// <param name="delimiter">Делитель размера</param>
/// <returns>Строка</returns>
public readonly string ToString (char delimiter = ':') => $"{_pWidth}{delimiter}{_pHeight}";
/// <summary>
/// Получение размера из строки
/// </summary>
/// <param name="s">Строка</param>
/// <param name="delimiter">Разделитель размеров</param>
/// <returns>Модель размеров</returns>
/// <exception cref="ArgumentOutOfRangeException">Если в строке <paramref name="s"/> не содержится символа
/// <paramref name="delimiter"/> или таких разделителей слишком много</exception>
public static TwoDimSize Parse (string s, char delimiter = ':')
{
// Разделяю значения
string[] splitSizes = s.Split(delimiter);
// Проверяю, что массив имеет ровно два элемента
if (splitSizes.Length != 2)
throw new ArgumentOutOfRangeException(delimiter.ToString(),
$"Похоже, что в строке {s} не содержится символа {delimiter} или таких разделителей слишком много!");
// Пытаюсь получить длину
if (!int.TryParse(splitSizes[0], out int width))
width = 0;
// Пытаюсь получить ширину
if (!int.TryParse(splitSizes[1], out int height))
height = 0;
// Вывожу значение
return new(width, height);
}
#endregion
#region Реализация интерфейса ISerializable
/// <summary>
/// Сериализовать элемент в формат json
/// </summary>
/// <returns>Строка в формате json</returns>
public readonly string Serialize () => new SysTextSerializer().Serialize(ToString());
/// <summary>
/// Восстановить элемент из формата json
/// </summary>
/// <param name="json">Строка в формате json</param>
public void Deserialize (string json)
{
// Десериализую строку
string deserialized = new SysTextSerializer().Deserialize<string>(json) ?? "0:0";
// Перевожу строку в двумерный размер
TwoDimSize result = Parse(deserialized);
// Присваиваю длину
_pWidth = result.Width;
// Присваиваю ширину
_pHeight = result.Height;
}
#endregion
} }

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<Version>2024.8.18</Version> <Version>2023.1101.1</Version>
<Authors>Александр Бабаев</Authors> <Authors>Александр Бабаев</Authors>
<Product>Набор компонентов ANB Software</Product> <Product>Набор компонентов ANB Software</Product>
<Description>Библиотека полезных методов языка C#</Description> <Description>Библиотека полезных методов языка C#</Description>
@ -22,7 +22,6 @@
<AnalysisLevel>6.0</AnalysisLevel> <AnalysisLevel>6.0</AnalysisLevel>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>Библиотека полезных методов и классов от ANB</Title>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@ -38,11 +37,15 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MimeTypes" Version="2.5.2"> <PackageReference Include="MimeTypes" Version="2.4.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Enums\" />
</ItemGroup>
</Project> </Project>

View File

@ -1,2 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp120</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp110</s:String></wpf:ResourceDictionary>

View File

@ -6,16 +6,18 @@ using MySqlConnector;
namespace anbs_cp.Database.Classes; namespace anbs_cp.Database.Classes;
/// <summary> public class MySqlEngine: IDbEngine
/// База данных MySQL
/// </summary>
/// <param name="connectionString">Строка подключения базы данных</param>
public class MySqlEngine (string connectionString): IDbEngine
{ {
/// <summary>
/// Конструктор
/// </summary>
/// <param name="connectionString">Строка подключения базы данных</param>
public MySqlEngine (string connectionString) => ConnectionString = connectionString;
/// <summary> /// <summary>
/// Строка подключения базы данных /// Строка подключения базы данных
/// </summary> /// </summary>
public string ConnectionString { get; set; } = connectionString; public string ConnectionString { get; set; }
#region Базовые операции #region Базовые операции
/// <summary> /// <summary>

View File

@ -1,4 +1,6 @@
namespace anbs_cp.Database.Interfaces; using System.Transactions;
namespace anbs_cp.Database.Interfaces;
/// <summary> /// <summary>
/// Интерфейс для работы с базой данных /// Интерфейс для работы с базой данных

View File

@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AssemblyName>anbs_cp_db</AssemblyName> <AssemblyName>anbs_cp_db</AssemblyName>
<RootNamespace>anbs_cp.Database</RootNamespace> <RootNamespace>anbs_cp.Database</RootNamespace>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>ANBSoftware.ComponentsPack.Database</PackageId> <PackageId>ANBSoftware.ComponentsPack.Database</PackageId>
<Version>2024.4.26</Version> <Version>2023.08.27.0</Version>
<Company>Александр Бабаев</Company> <Company>Александр Бабаев</Company>
<Product>Набор компонентов ANB Software для работы с БД</Product> <Product>Набор компонентов ANB Software для работы с БД</Product>
<Description>Библиотека полезных методов языка C# для работы с базами данных</Description> <Description>Библиотека полезных методов языка C# для работы с базами данных</Description>
@ -16,12 +16,11 @@
<PackageProjectUrl>https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack</PackageProjectUrl> <PackageProjectUrl>https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack</PackageProjectUrl>
<RepositoryUrl>https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack</RepositoryUrl> <RepositoryUrl>https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<Authors>Александр Бабаев</Authors>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Dapper" Version="2.1.35" /> <PackageReference Include="Dapper" Version="2.1.11" />
<PackageReference Include="MySqlConnector" Version="2.3.7" /> <PackageReference Include="MySqlConnector" Version="2.2.7" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,2 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp120</s:String></wpf:ResourceDictionary>

View File

@ -1,23 +0,0 @@
using Microsoft.Extensions.Configuration;
namespace anbs_cp.ForNet.Classes;
/// <summary>
/// Класс-поддержки для доступа к файлу "appsettings.json" в любом месте сайта классах.
/// Взято с: https://stackoverflow.com/a/69111159/16469671
/// </summary>
public static class AppSettings
{
// ReSharper disable once NotAccessedField.Global
// ReSharper disable once NotNullOrRequiredMemberIsNotInitialized
public static IConfiguration? Config { get; private set; }
/// <summary>
/// Инициализация настроек. Она проводится в файле Program.cs.
/// </summary>
/// <param name="configuration">Параметры из "appsettings.json"</param>
public static void Initialize (IConfiguration configuration)
{
Config = configuration;
}
}

View File

@ -1,118 +0,0 @@
using System.ComponentModel.DataAnnotations;
using anbs_cp.Classes;
using anbs_cp.ForNet.Constants;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
namespace anbs_cp.ForNet.Classes;
/// <summary>
/// Кастомные сообщения валидации формы
/// </summary>
/// <param name="messageList">Кастомный список сообщений формы</param>
public class CustomValidationMessages (KeyValueOrderedList<string>? messageList): IValidationMetadataProvider
{
/// <summary>
/// Список сообщений формы
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
public readonly KeyValueOrderedList<string> MessageList = messageList ?? ValidationMessagesConstants.English;
/// <summary>
/// Создаёт данные для локализации сообщений валидации
/// </summary>
/// <param name="context">Контекст</param>
public void CreateValidationMetadata (ValidationMetadataProviderContext context)
{
// Если context = null, то прерываем с ошибкой
ArgumentNullException.ThrowIfNull(context);
// Получаю мета-данные
IList<object>? validators = context.ValidationMetadata.ValidatorMetadata;
// Получаю тип модели
Type? theType = context.Key.ModelType;
// Получаю фундаментальный тип
Type? underlyingType = Nullable.GetUnderlyingType(theType);
// Проверяю получение и соответствие
if (theType.IsValueType && underlyingType == null &&
validators.All(m => m.GetType() != typeof(RequiredAttribute)))
// - задаю валидацию
validators.Add(new RequiredAttribute());
// Для каждого объекта валидации
foreach (object? obj in validators)
{
// - если он не атрибут
if (obj is not ValidationAttribute attribute)
// -- то продолжаю
continue;
// RequiredAttribute
FillErrorMessage<RequiredAttribute>(attribute);
// MinLengthAttribute
FillErrorMessage<MinLengthAttribute>(attribute);
// MaxLengthAttribute
FillErrorMessage<MaxLengthAttribute>(attribute);
// EmailAddressAttribute
FillErrorMessage<EmailAddressAttribute>(attribute);
// RangeAttribute
FillErrorMessage<RangeAttribute>(attribute);
// CompareAttribute
FillErrorMessage<CompareAttribute>(attribute);
// RegularExpressionAttribute
FillErrorMessage<RegularExpressionAttribute>(attribute);
// PhoneAttribute
FillErrorMessage<PhoneAttribute>(attribute);
// CreditCardAttribute
FillErrorMessage<CreditCardAttribute>(attribute);
}
}
/// <summary>
/// Устанавливает сообщение об ошибке валидации
/// </summary>
/// <typeparam name="T">Тип атрибута валидации</typeparam>
/// <param name="attribute">Атрибут</param>
private void FillErrorMessage<T> (object attribute) where T : ValidationAttribute
{
// Проверяю на соответствие типа
if (attribute is not T validationAttribute)
// - и прерываю, если не соответствует
return;
// Если нет сообщения об ошибке
if (validationAttribute.ErrorMessage == null && validationAttribute.ErrorMessageResourceName == null)
{
// - получаю имя аттрибута
string attributeTypeName = typeof(T).Name;
// - если список сообщений не содержит ключа с таким именем аттрибута
if (MessageList.Keys.All(s => s != attributeTypeName))
// -- то прерываю
return;
// - получаю предопределённое сообщение об ошибке
string? errorMessage = MessageList.GetValue(attributeTypeName);
// - если предопределённое сообщение пусто
if (errorMessage == null)
// -- то прерываю
return;
// - задаю значение
validationAttribute.ErrorMessage = errorMessage;
}
}
}

View File

@ -12,6 +12,6 @@ public class NetFileExtension
/// </summary> /// </summary>
/// <param name="file">Загружаемый файл</param> /// <param name="file">Загружаемый файл</param>
/// <returns>MIME-тип файла</returns> /// <returns>MIME-тип файла</returns>
public static string MimeType (IFormFile file) => public static string MIMEType (IFormFile file) =>
file.ContentType; file.ContentType;
} }

View File

@ -16,25 +16,17 @@ public sealed class PasswordEncrypt: IEncryptor
/// </summary> /// </summary>
/// <param name="password">Пароль</param> /// <param name="password">Пароль</param>
/// <param name="salt">Хэш-код пароля</param> /// <param name="salt">Хэш-код пароля</param>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <returns>Зашифрованный пароль</returns> /// <returns>Зашифрованный пароль</returns>
public string Encrypt (string password, string salt, string valueIfFail) public string Encrypt (string password, string salt)
{ {
try // Получаю byte-массив из хэш-кода пароля
{ byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
// Получаю byte-массив из хэш-кода пароля
byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
// Шифрую пароль // Шифрую пароль
byte[] encryptedPassword = KeyDerivation.Pbkdf2(password, saltBytes, KeyDerivationPrf.HMACSHA512, 5000, 64); byte[] encryptedPassword = KeyDerivation.Pbkdf2(password, saltBytes, KeyDerivationPrf.HMACSHA512, 5000, 64);
// Возвращаю зашифрованный пароль // Возвращаю зашифрованный пароль
return Convert.ToBase64String(encryptedPassword); return Convert.ToBase64String(encryptedPassword);
}
catch (FormatException)
{
return valueIfFail;
}
} }
/// <summary> /// <summary>
@ -43,28 +35,22 @@ public sealed class PasswordEncrypt: IEncryptor
/// <param name="encryptedValue">НЕ РАБОТАЕТ</param> /// <param name="encryptedValue">НЕ РАБОТАЕТ</param>
/// <param name="salt">НЕ РАБОТАЕТ</param> /// <param name="salt">НЕ РАБОТАЕТ</param>
/// <returns>НЕ РАБОТАЕТ</returns> /// <returns>НЕ РАБОТАЕТ</returns>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <exception cref="NotImplementedException">Этот метод не требует реализации в этом классе!</exception> /// <exception cref="NotImplementedException">Этот метод не требует реализации в этом классе!</exception>
public string Decrypt (string encryptedValue, string salt, string valueIfFail) => public string Decrypt (string encryptedValue, string salt) => throw new NotImplementedException("Этот метод не требует реализации в этом классе!");
throw new NotImplementedException("Этот метод не требует реализации в этом классе!");
/// <summary>
/// Этот метод не требует реализации в этом классе!
/// </summary>
/// <param name="text">НЕ РАБОТАЕТ</param>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <returns>НЕ РАБОТАЕТ</returns>
/// <exception cref="NotImplementedException">Этот метод не требует реализации в этом классе!</exception>
public string Base64UrlEncode (string text, string valueIfFail) =>
throw new NotImplementedException("Этот метод не требует реализации в этом классе!");
/// <summary> /// <summary>
/// Этот метод не требует реализации в этом классе! /// Этот метод не требует реализации в этом классе!
/// </summary> /// </summary>
/// <param name="text">НЕ РАБОТАЕТ</param> /// <param name="text">НЕ РАБОТАЕТ</param>
/// <returns>НЕ РАБОТАЕТ</returns> /// <returns>НЕ РАБОТАЕТ</returns>
/// <param name="valueIfFail">Значение, если неудача</param>
/// <exception cref="NotImplementedException">Этот метод не требует реализации в этом классе!</exception> /// <exception cref="NotImplementedException">Этот метод не требует реализации в этом классе!</exception>
public string Base64UrlDecode (string text, string valueIfFail) => public string Base64UrlEncode (string text) => throw new NotImplementedException("Этот метод не требует реализации в этом классе!");
throw new NotImplementedException("Этот метод не требует реализации в этом классе!");
/// <summary>
/// Этот метод не требует реализации в этом классе!
/// </summary>
/// <param name="text">НЕ РАБОТАЕТ</param>
/// <returns>НЕ РАБОТАЕТ</returns>
/// <exception cref="NotImplementedException">Этот метод не требует реализации в этом классе!</exception>
public string Base64UrlDecode (string text) => throw new NotImplementedException("Этот метод не требует реализации в этом классе!");
} }

View File

@ -1,208 +0,0 @@
using anbs_cp.ForNet.Enums;
using Ganss.Xss;
namespace anbs_cp.ForNet.Classes;
/// <summary>
/// Очистка текста от лишних HTML-тегов
/// </summary>
public static class Sanitizer
{
#region Свойства
/// <summary>
/// Все теги запрещены
/// </summary>
public static SanitizerAllowedHtml AllowedNone => GetNone();
/// <summary>
/// Все теги разрешены
/// </summary>
public static SanitizerAllowedHtml AllowedAll => GetAll();
/// <summary>
/// Оставлены только текстовые теги
/// </summary>
public static SanitizerAllowedHtml AllowedTextOnly => GetTextFormatOnly();
/// <summary>
/// Оставлены только текстовые теги, а также img и a
/// </summary>
public static SanitizerAllowedHtml AllowedImageAndLinks => GetImageAndLinks();
/// <summary>
/// Применяются все теги, кроме iframe
/// </summary>
public static SanitizerAllowedHtml AllowedAllExceptIFrame => GetAllExceptIFrame();
#endregion
#region Методы
/// <summary>
/// Очистка html-кода <paramref name="html" /> согласно параметрам <paramref name="allowedHtml" />
/// </summary>
/// <param name="html">HTML-код</param>
/// <param name="allowedHtml">Параметры очистки</param>
/// <returns>Очищенный html-кода</returns>
public static string SanitizeHtml (string html, SanitizerAllowedHtml allowedHtml)
{
// Создаю очиститель
HtmlSanitizer sanitizer = new()
{
// - сохраняю дочерние удалённых
KeepChildNodes = true
};
// Выключаю все параметры HTML
sanitizer.AllowedTags.Clear();
sanitizer.AllowedSchemes.Clear();
sanitizer.AllowedCssProperties.Clear();
sanitizer.AllowedClasses.Clear();
sanitizer.AllowedAttributes.Clear();
sanitizer.AllowedAtRules.Clear();
sanitizer.AllowDataAttributes = false;
// Загружаю параметры
sanitizer.AllowedTags.UnionWith(allowedHtml.AllowedTags);
sanitizer.AllowedSchemes.UnionWith(allowedHtml.AllowedSchemes);
sanitizer.AllowedCssProperties.UnionWith(allowedHtml.AllowedCssProperties);
sanitizer.AllowedClasses.UnionWith(allowedHtml.AllowedClasses);
sanitizer.AllowedAttributes.UnionWith(allowedHtml.AllowedAttributes);
sanitizer.AllowDataAttributes = allowedHtml.AllowDataAttributes;
// Очищаю html согласно правилам
return sanitizer.Sanitize(html);
}
/// <summary>
/// Очистка html-кода по уровню очистки
/// </summary>
/// <param name="html">HTML-код</param>
/// <param name="level">Уровень очистка</param>
/// <returns>Очищенный html-код</returns>
public static string SanitizeHtml (string html, ESanitizerLevel level)
{
// Получаю параметры очистки
SanitizerAllowedHtml allowedHtml = level switch
{
ESanitizerLevel.NoTags => AllowedNone,
ESanitizerLevel.TextFormatOnly => AllowedTextOnly,
ESanitizerLevel.ImageAndLinks => AllowedImageAndLinks,
ESanitizerLevel.AllExceptIFrame => AllowedAllExceptIFrame,
ESanitizerLevel.All => AllowedAll,
var _ => AllowedAll
};
// Очищаю код и возвращаю результат очистки
return SanitizeHtml(html, allowedHtml);
}
#endregion
#region Вспомогателдьные методы
/// <summary>
/// Получаю параметры, удаляющие все теги
/// </summary>
/// <returns>Параметры очистки</returns>
private static SanitizerAllowedHtml GetNone () =>
new()
{
AllowedTags = [],
AllowedAttributes = [],
AllowedCssProperties = [],
AllowedClasses = [],
AllowedSchemes = [],
AllowDataAttributes = false
};
/// <summary>
/// Получаю параметры по умолчанию (разрешающие все теги)
/// </summary>
/// <returns>Параметры очистки</returns>
private static SanitizerAllowedHtml GetAll ()
{
// Создаю очиститель
HtmlSanitizer sanitizer = new();
// Создаю модель
return new()
{
AllowedTags = sanitizer.AllowedTags.ToList(),
AllowedAttributes = sanitizer.AllowedAttributes.ToList(),
AllowedCssProperties = sanitizer.AllowedCssProperties.ToList(),
AllowedClasses = sanitizer.AllowedClasses.ToList(),
AllowedSchemes = sanitizer.AllowedSchemes.ToList(),
AllowDataAttributes = true
};
}
/// <summary>
/// Параметры, оставляющие только текстовые теги
/// </summary>
/// <returns>Параметры очистки</returns>
private static SanitizerAllowedHtml GetTextFormatOnly () =>
new()
{
AllowedTags =
[
"strong", "b", "em", "i", "u", "hr", "strike", "div", "ol", "ul", "li", "p", "span", "h1", "h2", "h3",
"h4"
],
// ReSharper disable StringLiteralTypo
AllowedAttributes =
[
"align", "bgcolor", "border", "cellpadding", "cellspacing", "charset", "checked", "class", "clear",
"color",
"cols", "colspan", "datetime", "disabled", "headers", "height", "high", "hspace", "label", "lang",
"list",
"low", "max", "maxlength", "min", "name", "nowrap", "placeholder", "required", "rev", "rows", "rowspan",
"rules", "selected", "size", "span", "spellcheck", "style", "summary", "tabindex", "title", "type",
"valign",
"value", "vspace", "width", "wrap"
]
// ReSharper restore StringLiteralTypo
};
/// <summary>
/// Параметры, оставляющие только текстовые теги, а также img и a
/// </summary>
/// <returns>Параметры очистки</returns>
private static SanitizerAllowedHtml GetImageAndLinks ()
{
// Получаю текстовые параметры
SanitizerAllowedHtml result = AllowedTextOnly;
// Добавляю теги
result.AllowedTags.AddRange(["a", "img"]);
// Добавляю параметры
// ReSharper disable StringLiteralTypo
result.AllowedAttributes.AddRange(["alt", "href", "hreflang", "nohref", "rel", "src", "target"]);
// ReSharper restore StringLiteralTypo
// Возвращаю результат
return result;
}
/// <summary>
/// Применяются все теги, кроме iframe
/// </summary>
/// <returns>Параметры очистки</returns>
private static SanitizerAllowedHtml GetAllExceptIFrame ()
{
// Получаю все параметры
SanitizerAllowedHtml result = AllowedAll;
// Удаляю iframe
result.AllowedTags.Remove("iframe");
// Возвращаю результат
return result;
}
#endregion
}

View File

@ -1,37 +0,0 @@
namespace anbs_cp.ForNet.Classes;
/// <summary>
/// Допустимые параметры для очистки HTML
/// </summary>
public sealed class SanitizerAllowedHtml
{
/// <summary>
/// Допустимые теги
/// </summary>
public List<string> AllowedTags { get; set; } = [];
/// <summary>
/// Допустимые аттрибуты
/// </summary>
public List<string> AllowedAttributes { get; set; } = [];
/// <summary>
/// Допустимые параметры css
/// </summary>
public List<string> AllowedCssProperties { get; set; } = [];
/// <summary>
/// Допустимые классы
/// </summary>
public List<string> AllowedClasses { get; set; } = [];
/// <summary>
/// Допустимые схемы
/// </summary>
public List<string> AllowedSchemes { get; set; } = [];
/// <summary>
/// Допустимы ли data-атрибуты
/// </summary>
public bool AllowDataAttributes { get; set; } = false;
}

View File

@ -1,41 +0,0 @@
using anbs_cp.Classes;
namespace anbs_cp.ForNet.Constants;
/// <summary>
/// Сообщения валидации
/// </summary>
public static class ValidationMessagesConstants
{
/// <summary>
/// Сообщения на русском языке
/// </summary>
public static readonly KeyValueOrderedList<string> Russian =
[
new("RequiredAttribute", "Поле '{0}' обязательно к заполнению."),
new("MinLengthAttribute", "Минимальная длина поля '{0}' от {1} символа(-ов)."),
new("MaxLengthAttribute", "Максимальная длина поля '{0}' до {1} символа(-ов)."),
new("EmailAddressAttribute", "Адрес email некорректен."),
new("RangeAttribute", "Значение поля '{0}' должно быть между {1} и {2}."),
new("CompareAttribute", "Значение поля '{0}' не совпадаем с требуемым."),
new("RegularExpressionAttribute", "Значение поля '{0}' не удовлетворяет шаблону."),
new ("PhoneAttribute", "Значение поля '{0}' не является номером телефона."),
new ("CreditCardAttribute", "Значение поля '{0}' не является номером кредитной карты.")
];
/// <summary>
/// Сообщения на английском языке
/// </summary>
public static readonly KeyValueOrderedList<string> English =
[
new("RequiredAttribute", "You must fill in '{0}'."),
new("MinLengthAttribute", "Min length of '{0}' is {1}."),
new("MaxLengthAttribute", "Max length of '{0}' is {1}."),
new("EmailAddressAttribute", "Invalid email address."),
new("RangeAttribute", "The value of the field '{0}' must be between {1} and {2}."),
new("CompareAttribute", "Unmatched field '{0}' value."),
new("RegularExpressionAttribute", "Invalid field '{0}' value."),
new ("PhoneAttribute", "The value of the field '{0}' is not valid phone number."),
new ("CreditCardAttribute", "The value of the field '{0}' is not valid credit card number.")
];
}

View File

@ -1,38 +0,0 @@
namespace anbs_cp.ForNet.Enums;
/// <summary>
/// Уровень очистки текста
/// атрибуты описаны на стр. https://github.com/mganss/HtmlSanitizer/wiki/Options
/// </summary>
public enum ESanitizerLevel
{
/// <summary>
/// Все html-теги под запретом
/// </summary>
NoTags = 0,
/// <summary>
/// Доступны только:
/// * теги формата шрифта (жирный, курсив, подчёркнутый, зачёркнутый)
/// * теги расположения текста (слева, по центру, справа)
/// </summary>
TextFormatOnly = 1,
/// <summary>
/// Доступны только:
/// * все теги уровня lvlTextFormatOnly
/// * теги ссылки
/// * теги изображения
/// </summary>
ImageAndLinks = 2,
/// <summary>
/// Доступны все теги, кроме вставки с другого сайта
/// </summary>
AllExceptIFrame = 3,
/// <summary>
/// Доступны все теги
/// </summary>
All = 4
}

View File

@ -1,108 +0,0 @@
using System.Text.RegularExpressions;
using ImageMagick;
using Microsoft.AspNetCore.Http;
using static System.Text.RegularExpressions.Regex;
namespace anbs_cp.ForNet.Extensions;
/// <summary>
/// Расширение интерфейса IFormFile
/// </summary>
public static class FormFileExtension
{
#region Константы
/// <summary>
/// Минимальный размер изображения (в байтах)
/// </summary>
private const int ImageMinimumBytes = 512;
/// <summary>
/// Список поддерживаемых Mime-типов
/// </summary>
private static readonly List<string> AllowedMimeTypes =
["image/jpg", "image/jpeg", "image/pjpeg", "image/gif", "image/x-png", "image/png"];
/// <summary>
/// Список поддерживаемых расширений файлов
/// </summary>
private static readonly List<string> AllowedExtensions = [".jpg", ".png", ".gif", ".jpeg"];
#endregion
/// <summary>
/// Получение содержимого файла
/// </summary>
/// <param name="file">Файл из формы</param>
/// <returns>Содержимое файла</returns>
public static byte[] GetFileContent (this IFormFile file)
{
// Читаем содержимое файла
using BinaryReader binaryReader = new(file.OpenReadStream());
// Создаю контент изображения
byte[] content = binaryReader.ReadBytes((int)file.Length);
// Вывожу результат
return content;
}
/// <summary>
/// Проверка, является ли файл изображением
/// </summary>
/// <param name="postedFile">Файл из формы</param>
/// <returns>Является ли файл изображением</returns>
public static bool IsImage (this IFormFile postedFile)
{
// Проверяю Mime-тип
if (!AllowedMimeTypes.Contains(postedFile.ContentType.ToLower()))
return false;
// Проверяю расширение
if (!AllowedExtensions.Contains(Path.GetExtension(postedFile.FileName).ToLower()))
return false;
// Пытаюсь прочитать файл и проверить первые байты
try
{
if (!postedFile.OpenReadStream().CanRead)
return false;
// Проверяю, не меньше ли размер изображения установленного предела
if (postedFile.Length < ImageMinimumBytes)
return false;
byte[] buffer = new byte[ImageMinimumBytes];
int _ = postedFile.OpenReadStream().Read(buffer, 0, ImageMinimumBytes);
string content = System.Text.Encoding.UTF8.GetString(buffer);
if (IsMatch(content,
@"<script|<html|<head|<title|<body|<pre|<table|<a\s+href|<img|<plaintext|<cross\-domain\-policy",
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Multiline))
return false;
}
catch (Exception)
{
// - если .NET выдаст исключение, то можно предположить, что это недопустимое изображение
return false;
}
// Попробую создать экземпляр MagickImageCollection,
try
{
using MagickImageCollection images = new(postedFile.OpenReadStream());
}
catch (Exception)
{
// - если .NET выдаст исключение, то можно предположить, что это недопустимое изображение
return false;
}
finally
{
postedFile.OpenReadStream().Position = 0;
}
// Возвращаю, что это изображение
return true;
}
}

View File

@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>ANBSoftware.ComponentsPackForNet</PackageId> <PackageId>ANBSoftware.ComponentsPackForNet</PackageId>
<Version>2024.9.1</Version> <Version>2023.09.08.0</Version>
<Authors>Александр Бабаев</Authors> <Authors>Александр Бабаев</Authors>
<Product>Набор компонентов ANB Software для ASP.NET Core</Product> <Product>Набор компонентов ANB Software для ASP.NET Core</Product>
<Description>Библиотека полезных методов языка C# для ASP.NET Core</Description> <Description>Библиотека полезных методов языка C# для ASP.NET Core</Description>
@ -20,18 +20,19 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="HtmlSanitizer" Version="8.1.870" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="7.0.12" />
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="13.10.0" />
<PackageReference Include="Magick.NET.Core" Version="13.10.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.TagHelpers" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="8.0.8" /> <PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\anbs_cp\anbs_cp.csproj" /> <ProjectReference Include="..\anbs_cp\anbs_cp.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Extensions\" />
</ItemGroup>
</Project> </Project>

View File

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>anbs_cp.OsInfo</RootNamespace> <RootNamespace>anbs_cp.OsInfo</RootNamespace>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>ANBSoftware.ComponentsPackOsInfo</PackageId> <PackageId>ANBSoftware.ComponentsPackOsInfo</PackageId>
<Version>2023.11.14</Version> <Version>2023.8.11</Version>
<Authors>Александр Бабаев</Authors> <Authors>Александр Бабаев</Authors>
<Product>Набор компонентов ANB Software для получения информации о Windows</Product> <Product>Набор компонентов ANB Software для получения информации о Windows</Product>
<Description>Библиотека полезных методов языка C# для получения информации об Windows</Description> <Description>Библиотека полезных методов языка C# для получения информации об Windows</Description>
@ -18,11 +18,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Management" Version="8.0.0" /> <PackageReference Include="ANBSoftware.ComponentsPack" Version="2023.811.0" />
</ItemGroup> <PackageReference Include="System.Management" Version="7.0.2" />
<ItemGroup>
<ProjectReference Include="..\anbs_cp\anbs_cp.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,2 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp120</s:String></wpf:ResourceDictionary>

View File

@ -11,18 +11,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "demo", "demo\demo.csproj",
EndProjectSection EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cpfn", "anbs_cpfn\anbs_cpfn.csproj", "{EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cpfn", "anbs_cpfn\anbs_cpfn.csproj", "{EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}"
EndProject ProjectSection(ProjectDependencies) = postProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cposinfo", "anbs_cposinfo\anbs_cposinfo.csproj", "{80E1FEA9-EEDA-4411-8EBA-11991432E98E}" {442A56CC-1061-4EB5-8B67-3E3D997976D7} = {442A56CC-1061-4EB5-8B67-3E3D997976D7}
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cpdb", "anbs_cpdb\anbs_cpdb.csproj", "{3796862F-F181-4A27-92D8-8BF13C4FD711}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "demo2", "demo2\demo2.csproj", "{ED9A2B81-5060-4906-AAC4-88ED1C70211E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F9AFD424-6FCE-465A-8EEF-DA99D3350696}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "anbs_cposinfo", "anbs_cposinfo\anbs_cposinfo.csproj", "{80E1FEA9-EEDA-4411-8EBA-11991432E98E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "anbs_cpdb", "anbs_cpdb\anbs_cpdb.csproj", "{3796862F-F181-4A27-92D8-8BF13C4FD711}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -48,10 +44,6 @@ Global
{3796862F-F181-4A27-92D8-8BF13C4FD711}.Debug|Any CPU.Build.0 = Debug|Any CPU {3796862F-F181-4A27-92D8-8BF13C4FD711}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3796862F-F181-4A27-92D8-8BF13C4FD711}.Release|Any CPU.ActiveCfg = Release|Any CPU {3796862F-F181-4A27-92D8-8BF13C4FD711}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3796862F-F181-4A27-92D8-8BF13C4FD711}.Release|Any CPU.Build.0 = Release|Any CPU {3796862F-F181-4A27-92D8-8BF13C4FD711}.Release|Any CPU.Build.0 = Release|Any CPU
{ED9A2B81-5060-4906-AAC4-88ED1C70211E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED9A2B81-5060-4906-AAC4-88ED1C70211E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED9A2B81-5060-4906-AAC4-88ED1C70211E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED9A2B81-5060-4906-AAC4-88ED1C70211E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -2,54 +2,27 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CD/@EntryIndexedValue">CD</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CD/@EntryIndexedValue">CD</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HD/@EntryIndexedValue">HD</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HD/@EntryIndexedValue">HD</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HDD/@EntryIndexedValue">HDD</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HDD/@EntryIndexedValue">HDD</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RA/@EntryIndexedValue">RA</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RA/@EntryIndexedValue">RA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RAM/@EntryIndexedValue">RAM</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RAM/@EntryIndexedValue">RAM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=URL/@EntryIndexedValue">URL</s:String>
<s:Boolean x:Key="/Default/GrammarAndSpelling/GrammarChecking/Exceptions/=_0412_044B_0447_0438_0441_043B_044F_0435_0442_002C_0020_0435_0441_0442_044C_0020_043B_0438_0020_0445_043E_0442_044F_0020_0431_044B_0020_043E_0434_043D_043E_0020_0438_0437_0020_0431_0443_043B_0435_0432_044B_0445_0020_043F_0435_0440_0435_043C_0435_043D_043D_044B_0445_0020reference_0432_0020_0437_043D_0430_0447_0435_043D_0438_0438/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=abcdefghijkmnopqrstuvwxyz/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=abcdefghijkmnopqrstuvwxyz/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ABCDEFGHJKLMNOPQRSTUVWXYZ/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=ABCDEFGHJKLMNOPQRSTUVWXYZ/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=anbs/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=anbs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=appsettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=C_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_044F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Darkseal/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Darkseal/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=delim/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Encryptor/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Encryptor/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Glendower/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Glendower/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=pjpeg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=splited/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0412_0435_0440_043D_0451_043C/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0412_0435_0440_043D_0451_043C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0412_0438_0434_0435_043E_043A_0430_0440_0442_0430/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0412_0438_0434_0435_043E_043A_0430_0440_0442_0430/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0414_0435_0441_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_043D_043D_044B_0439/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0414_0435_0441_0435_0440_0438_0430_043B_0438_0437_0443_0435_043C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0414_0435_0441_0435_0440_0438_0430_043B_0438_0437_0443_044E/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_041F_0430_0440_0441_0435_0440/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_041F_0430_0440_0441_0435_0440/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0421_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_043D_043D_0430_044F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0421_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_043D_043D_044B_0435/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0421_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_0442_044C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0421_0435_0440_0438_0430_043B_0438_0437_0443_0435_043C_043E_0435/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0421_043E_0437_0434_0430_0451_043C/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0421_043E_0437_0434_0430_0451_043C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0432_0432_0435_0434_0451_043D/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0432_0432_0435_0434_0451_043D/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0432_0438_0434_0435_043E_043A_0430_0440_0442_0435/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0432_0438_0434_0435_043E_043A_0430_0440_0442_0435/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_0435_0439/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_0438/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_044F/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_044F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0448_0438_0444_0440_043E_0432_0430_043D_0438_044F/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0448_0438_0444_0440_043E_0432_0430_043D_0438_044F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0448_0438_0444_0440_043E_0432_0447_0438_043A/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0448_0438_0444_0440_043E_0432_0447_0438_043A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0437_0430_0447_0451_0440_043A_043D_0443_0442_044B_0439/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0438_043C_0451_043D/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0438_043C_0451_043D/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043A_0440_0438_043F_0442_043E_0433_0440_0430_0444/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_043A_0440_0438_043F_0442_043E_0433_0440_0430_0444/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043F_043E_0434_0447_0451_0440_043A_043D_0443_0442_044B_0439/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043F_0443_0442_0451_043C/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_043F_0443_0442_0451_043C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0440_0435_0433_0438_0441_0442_0440_043E_0437_0430_0432_0438_0441_0438_043C_043E_0441_0442_044C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0430_0442_043E_0440_0430/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_0438/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_044F/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_044F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_043D_043D_043E_0433_043E/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_043D_043D_043E_0435/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_043D_043D_0443_044E/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0443_0435_043C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0443_044E/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0447_0451_0442/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0447_0451_0442/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0447_0451_0442_0447_0438_043A/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0447_0451_0442_0447_0438_043A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0445_044D_0448_0430/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=_0445_044D_0448_0430/@EntryIndexedValue">True</s:Boolean>

View File

@ -1,92 +0,0 @@
namespace demo;
sealed partial class ActionStateSerialize
{
/// <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 ()
{
textBox1 = new TextBox();
textBox2 = new TextBox();
label1 = new Label();
button1 = new Button();
SuspendLayout();
//
// textBox1
//
textBox1.Location = new Point(24, 12);
textBox1.Name = "textBox1";
textBox1.Size = new Size(209, 23);
textBox1.TabIndex = 0;
//
// textBox2
//
textBox2.Location = new Point(312, 6);
textBox2.Multiline = true;
textBox2.Name = "textBox2";
textBox2.Size = new Size(463, 225);
textBox2.TabIndex = 1;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(24, 65);
label1.Name = "label1";
label1.Size = new Size(38, 15);
label1.TabIndex = 2;
label1.Text = "label1";
//
// button1
//
button1.Location = new Point(24, 111);
button1.Name = "button1";
button1.Size = new Size(75, 23);
button1.TabIndex = 3;
button1.Text = "button1";
button1.UseVisualStyleBackColor = true;
button1.Click += button1_Click;
//
// ActionStateSerialize
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 250);
Controls.Add(button1);
Controls.Add(label1);
Controls.Add(textBox2);
Controls.Add(textBox1);
Name = "ActionStateSerialize";
Text = "Тест сериализации ActionState";
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox textBox1;
private TextBox textBox2;
private Label label1;
private Button button1;
}

View File

@ -1,34 +0,0 @@
using anbs_cp.Classes;
namespace demo;
public sealed partial class ActionStateSerialize: Form
{
public ActionStateSerialize ()
{
InitializeComponent();
}
private void button1_Click (object sender, EventArgs e)
{
DemoClass demoClass = new()
{
Name = textBox1.Text.Length > 0 ? textBox1.Text : string.Empty
};
ActionState<DemoClass> state = new()
{
Value = demoClass
};
state.AddError("ОШИБКА, ШЕФ!");
textBox2.Text = state.Serialize();
ActionState<DemoClass> state2 = new();
state2.Deserialize(textBox2.Text);
label1.Text = state2.Value?.Name ?? "НЕТ ЗНАЧЕНИЯ";
}
}

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,8 +0,0 @@
namespace demo;
public class DemoClass
{
public int Num { get; set; } = 5;
public string Name { get; set; } = "";
public bool NotB { get; set; } = true;
}

View File

@ -1,6 +1,4 @@
using anbs_cp.Classes; using anbs_cp.Classes;
using anbs_cp.Extensions;
// ReSharper disable LocalizableElement // ReSharper disable LocalizableElement
namespace demo; namespace demo;
@ -17,7 +15,7 @@ public sealed partial class FileHashAndMimeType: Form
openFileDialog.ShowDialog(); openFileDialog.ShowDialog();
} }
private void GetFileHashAndMimeType () private void GetFileHashAndMimeType()
{ {
if (string.IsNullOrEmpty(fileNameEdt.Text)) if (string.IsNullOrEmpty(fileNameEdt.Text))
{ {
@ -26,7 +24,7 @@ public sealed partial class FileHashAndMimeType: Form
} }
string fileHash = new FileHash(fileNameEdt.Text).ToString(); string fileHash = new FileHash(fileNameEdt.Text).ToString();
string fileType = FileExtension.MimeType(fileNameEdt.Text); string fileType = FileExtension.MIMEType(fileNameEdt.Text);
ResultLabel.Text = ResultLabel.Text =
$"Ïîëó÷åíû ñëåäóþùèå äàííûå äëÿ ôàéëà\r\n{fileNameEdt.Text}\r\nÕýø ôàéëà:\r\n{fileHash}\r\nÒèï ôàéëà:\r\n{fileType}"; $"Ïîëó÷åíû ñëåäóþùèå äàííûå äëÿ ôàéëà\r\n{fileNameEdt.Text}\r\nÕýø ôàéëà:\r\n{fileHash}\r\nÒèï ôàéëà:\r\n{fileType}";

View File

@ -28,95 +28,69 @@ sealed partial class MainMenu
/// </summary> /// </summary>
private void InitializeComponent () private void InitializeComponent ()
{ {
CountValueTest = new Button(); this.CountValueTest = new System.Windows.Forms.Button();
SimpleMapperTest = new Button(); this.SimpleMapperTest = new System.Windows.Forms.Button();
FileExtensionTest = new Button(); this.FileExtensionTest = new System.Windows.Forms.Button();
OsInfoBtn = new Button(); this.OsInfoBtn = new System.Windows.Forms.Button();
actionStateSerializerTestBtn = new Button(); this.SuspendLayout();
stringExtensionTestButton = new Button(); //
SuspendLayout(); // CountValueTest
// //
// CountValueTest this.CountValueTest.Location = new System.Drawing.Point(12, 12);
// this.CountValueTest.Name = "CountValueTest";
CountValueTest.Location = new Point(12, 12); this.CountValueTest.Size = new System.Drawing.Size(337, 53);
CountValueTest.Name = "CountValueTest"; this.CountValueTest.TabIndex = 0;
CountValueTest.Size = new Size(337, 53); this.CountValueTest.Text = "Новый тест модуля форматирования строки";
CountValueTest.TabIndex = 0; this.CountValueTest.UseVisualStyleBackColor = true;
CountValueTest.Text = "Новый тест модуля форматирования строки"; this.CountValueTest.Click += new System.EventHandler(this.button1_Click);
CountValueTest.UseVisualStyleBackColor = true; //
CountValueTest.Click += button1_Click; // SimpleMapperTest
// //
// SimpleMapperTest this.SimpleMapperTest.Location = new System.Drawing.Point(12, 71);
// this.SimpleMapperTest.Name = "SimpleMapperTest";
SimpleMapperTest.Location = new Point(12, 71); this.SimpleMapperTest.Size = new System.Drawing.Size(335, 51);
SimpleMapperTest.Name = "SimpleMapperTest"; this.SimpleMapperTest.TabIndex = 1;
SimpleMapperTest.Size = new Size(335, 51); this.SimpleMapperTest.Text = "Новый тест модуля SimpleMapper";
SimpleMapperTest.TabIndex = 1; this.SimpleMapperTest.UseVisualStyleBackColor = true;
SimpleMapperTest.Text = "Новый тест модуля SimpleMapper"; this.SimpleMapperTest.Click += new System.EventHandler(this.SimpleMapperTest_Click);
SimpleMapperTest.UseVisualStyleBackColor = true; //
SimpleMapperTest.Click += SimpleMapperTest_Click; // FileExtensionTest
// //
// FileExtensionTest this.FileExtensionTest.Location = new System.Drawing.Point(12, 128);
// this.FileExtensionTest.Name = "FileExtensionTest";
FileExtensionTest.Location = new Point(12, 128); this.FileExtensionTest.Size = new System.Drawing.Size(335, 51);
FileExtensionTest.Name = "FileExtensionTest"; this.FileExtensionTest.TabIndex = 2;
FileExtensionTest.Size = new Size(335, 51); this.FileExtensionTest.Text = "Новый тест модуля FileExtension";
FileExtensionTest.TabIndex = 2; this.FileExtensionTest.UseVisualStyleBackColor = true;
FileExtensionTest.Text = "Новый тест модуля FileExtension"; this.FileExtensionTest.Click += new System.EventHandler(this.FileExtensionTest_Click);
FileExtensionTest.UseVisualStyleBackColor = true; //
FileExtensionTest.Click += FileExtensionTest_Click; // OsInfoBtn
// //
// OsInfoBtn this.OsInfoBtn.Location = new System.Drawing.Point(12, 185);
// this.OsInfoBtn.Name = "OsInfoBtn";
OsInfoBtn.Location = new Point(12, 185); this.OsInfoBtn.Size = new System.Drawing.Size(335, 51);
OsInfoBtn.Name = "OsInfoBtn"; this.OsInfoBtn.TabIndex = 3;
OsInfoBtn.Size = new Size(335, 51); this.OsInfoBtn.Text = "Информация о системе";
OsInfoBtn.TabIndex = 3; this.OsInfoBtn.UseVisualStyleBackColor = true;
OsInfoBtn.Text = "Информация о системе"; this.OsInfoBtn.Click += new System.EventHandler(this.OsInfoBtn_Click);
OsInfoBtn.UseVisualStyleBackColor = true; //
OsInfoBtn.Click += OsInfoBtn_Click; // MainMenu
// //
// actionStateSerializerTestBtn this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 21F);
// this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
actionStateSerializerTestBtn.Location = new Point(12, 242); this.ClientSize = new System.Drawing.Size(361, 252);
actionStateSerializerTestBtn.Name = "actionStateSerializerTestBtn"; this.Controls.Add(this.OsInfoBtn);
actionStateSerializerTestBtn.Size = new Size(335, 51); this.Controls.Add(this.FileExtensionTest);
actionStateSerializerTestBtn.TabIndex = 4; this.Controls.Add(this.SimpleMapperTest);
actionStateSerializerTestBtn.Text = "Тест сериализации ActionState"; this.Controls.Add(this.CountValueTest);
actionStateSerializerTestBtn.UseVisualStyleBackColor = true; this.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
actionStateSerializerTestBtn.Click += actionStateSerializerTestBtn_Click; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
// this.Margin = new System.Windows.Forms.Padding(4);
// stringExtensionTestButton this.Name = "MainMenu";
// this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
stringExtensionTestButton.Location = new Point(12, 299); this.Text = "Главное меню";
stringExtensionTestButton.Name = "stringExtensionTestButton"; this.ResumeLayout(false);
stringExtensionTestButton.Size = new Size(335, 51);
stringExtensionTestButton.TabIndex = 5;
stringExtensionTestButton.Text = "Тест расширения класса string";
stringExtensionTestButton.UseVisualStyleBackColor = true;
stringExtensionTestButton.Click += stringExtensionTestButton_Click;
//
// MainMenu
//
AutoScaleDimensions = new SizeF(10F, 21F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(361, 361);
Controls.Add(stringExtensionTestButton);
Controls.Add(actionStateSerializerTestBtn);
Controls.Add(OsInfoBtn);
Controls.Add(FileExtensionTest);
Controls.Add(SimpleMapperTest);
Controls.Add(CountValueTest);
Font = new Font("Times New Roman", 14.25F);
FormBorderStyle = FormBorderStyle.FixedSingle;
Margin = new Padding(4);
MaximizeBox = false;
MinimizeBox = false;
Name = "MainMenu";
ShowIcon = false;
StartPosition = FormStartPosition.CenterScreen;
Text = "Главное меню";
ResumeLayout(false);
} }
#endregion #endregion
@ -125,6 +99,4 @@ sealed partial class MainMenu
private Button SimpleMapperTest; private Button SimpleMapperTest;
private Button FileExtensionTest; private Button FileExtensionTest;
private Button OsInfoBtn; private Button OsInfoBtn;
private Button actionStateSerializerTestBtn;
private Button stringExtensionTestButton;
} }

View File

@ -1,6 +1,4 @@
using demo.TestForms; namespace demo;
namespace demo;
public sealed partial class MainMenu: Form public sealed partial class MainMenu: Form
{ {
public MainMenu () public MainMenu ()
@ -31,16 +29,4 @@ public sealed partial class MainMenu: Form
OsInfoFrm formTest = new(); OsInfoFrm formTest = new();
formTest.ShowDialog(); formTest.ShowDialog();
} }
private void actionStateSerializerTestBtn_Click (object sender, EventArgs e)
{
ActionStateSerialize form = new();
form.ShowDialog();
}
private void stringExtensionTestButton_Click (object sender, EventArgs e)
{
StringExtensionTest form = new();
form.ShowDialog();
}
} }

View File

@ -1,64 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <root>
<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: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:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">

View File

@ -1,5 +1,6 @@
using anbs_cp.Classes; using anbs_cp.OsInfo.Classes;
using anbs_cp.OsInfo.Classes;
using Newtonsoft.Json;
namespace demo; namespace demo;
public sealed partial class OsInfoFrm: Form public sealed partial class OsInfoFrm: Form
@ -12,16 +13,16 @@ public sealed partial class OsInfoFrm: Form
private void OsInfoFrm_Load (object sender, EventArgs e) private void OsInfoFrm_Load (object sender, EventArgs e)
{ {
textBox.Text = @"Процессор(ы) | "; textBox.Text = @"Процессор(ы) | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.Processors); textBox.Text += JsonConvert.SerializeObject(OsInfo.Processors);
textBox.Text += @"Оперативная память | "; textBox.Text += @"Оперативная память | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.RAM); textBox.Text += JsonConvert.SerializeObject(OsInfo.RAM);
textBox.Text += @"Видеокарта | "; textBox.Text += @"Видеокарта | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.Videos); textBox.Text += JsonConvert.SerializeObject(OsInfo.Videos);
textBox.Text += @"Диски | "; textBox.Text += @"Диски | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.Drives); textBox.Text += JsonConvert.SerializeObject(OsInfo.Drives);
textBox.Text += @"Windows | "; textBox.Text += @"Windows | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.Windows); textBox.Text += JsonConvert.SerializeObject(OsInfo.Windows);
textBox.Text += @"Net | "; textBox.Text += @"Net | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.Net); textBox.Text += JsonConvert.SerializeObject(OsInfo.Net);
} }
} }

View File

@ -1,4 +1,5 @@
using anbs_cp.Classes; using anbs_cp.Classes;
using Newtonsoft.Json;
namespace demo; namespace demo;
public sealed partial class SampleMapperTest: Form public sealed partial class SampleMapperTest: Form
@ -25,7 +26,7 @@ public sealed partial class SampleMapperTest: Form
DemoDateTime = default DemoDateTime = default
}; };
string serialize1 = new SysTextSerializer().Serialize(demo2); string serialize1 = JsonConvert.SerializeObject(demo2);
SimpleMapper.MapMode mode = MapModeEdit.SelectedIndex switch SimpleMapper.MapMode mode = MapModeEdit.SelectedIndex switch
{ {
@ -38,7 +39,7 @@ public sealed partial class SampleMapperTest: Form
SimpleMapper.MapEx(demo1, ref demo2, mode, new List<string>()); SimpleMapper.MapEx(demo1, ref demo2, mode, new List<string>());
string serialize2 = new SysTextSerializer().Serialize(demo2); string serialize2 = JsonConvert.SerializeObject(demo2);
// ReSharper disable once LocalizableElement // ReSharper disable once LocalizableElement
ResultArea.Text = $"Класс Demo2 до связывания:\r\n{serialize1}\r\nи после:\r\n{serialize2}"; ResultArea.Text = $"Класс Demo2 до связывания:\r\n{serialize1}\r\nи после:\r\n{serialize2}";

View File

@ -1,92 +0,0 @@
namespace demo.TestForms;
sealed partial class ActionStateSerialize
{
/// <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 ()
{
textBox1 = new TextBox();
textBox2 = new TextBox();
label1 = new Label();
button1 = new Button();
SuspendLayout();
//
// textBox1
//
textBox1.Location = new Point(24, 12);
textBox1.Name = "textBox1";
textBox1.Size = new Size(209, 23);
textBox1.TabIndex = 0;
//
// textBox2
//
textBox2.Location = new Point(312, 6);
textBox2.Multiline = true;
textBox2.Name = "textBox2";
textBox2.Size = new Size(463, 225);
textBox2.TabIndex = 1;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(24, 65);
label1.Name = "label1";
label1.Size = new Size(38, 15);
label1.TabIndex = 2;
label1.Text = "label1";
//
// button1
//
button1.Location = new Point(24, 111);
button1.Name = "button1";
button1.Size = new Size(75, 23);
button1.TabIndex = 3;
button1.Text = "button1";
button1.UseVisualStyleBackColor = true;
button1.Click += button1_Click;
//
// ActionStateSerialize
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 250);
Controls.Add(button1);
Controls.Add(label1);
Controls.Add(textBox2);
Controls.Add(textBox1);
Name = "ActionStateSerialize";
Text = "Тест сериализации ActionState";
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox textBox1;
private TextBox textBox2;
private Label label1;
private Button button1;
}

View File

@ -1,34 +0,0 @@
using anbs_cp.Classes;
namespace demo.TestForms;
public sealed partial class ActionStateSerialize: Form
{
public ActionStateSerialize ()
{
InitializeComponent();
}
private void button1_Click (object sender, EventArgs e)
{
DemoClass demoClass = new()
{
Name = textBox1.Text.Length > 0 ? textBox1.Text : string.Empty
};
ActionState<DemoClass> state = new()
{
Value = demoClass
};
state.AddError("ОШИБКА, ШЕФ!");
textBox2.Text = state.Serialize();
ActionState<DemoClass> state2 = new();
state2.Deserialize(textBox2.Text);
label1.Text = state2.Value?.Name ?? "НЕТ ЗНАЧЕНИЯ";
}
}

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,147 +0,0 @@
namespace demo.TestForms;
sealed partial class CountValueTest
{
/// <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 ()
{
this.InsertDataLabel = new System.Windows.Forms.Label();
this.InsertDataBox = new System.Windows.Forms.TextBox();
this.ResultLabel = new System.Windows.Forms.Label();
this.CalculateButton = new System.Windows.Forms.Button();
this.SelectFormatterLabel = new System.Windows.Forms.Label();
this.SelectFormatterBox = new System.Windows.Forms.ComboBox();
this.calculateConvButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// InsertDataLabel
//
this.InsertDataLabel.AutoSize = true;
this.InsertDataLabel.Location = new System.Drawing.Point(12, 66);
this.InsertDataLabel.Name = "InsertDataLabel";
this.InsertDataLabel.Size = new System.Drawing.Size(341, 17);
this.InsertDataLabel.TabIndex = 0;
this.InsertDataLabel.Text = "&Введите любое целочисленное значение:";
//
// InsertDataBox
//
this.InsertDataBox.Location = new System.Drawing.Point(12, 86);
this.InsertDataBox.Name = "InsertDataBox";
this.InsertDataBox.Size = new System.Drawing.Size(457, 24);
this.InsertDataBox.TabIndex = 1;
this.InsertDataBox.TextChanged += new System.EventHandler(this.InsertDataBox_TextChanged);
//
// ResultLabel
//
this.ResultLabel.Dock = System.Windows.Forms.DockStyle.Bottom;
this.ResultLabel.Location = new System.Drawing.Point(0, 143);
this.ResultLabel.Margin = new System.Windows.Forms.Padding(5);
this.ResultLabel.Name = "ResultLabel";
this.ResultLabel.Padding = new System.Windows.Forms.Padding(5);
this.ResultLabel.Size = new System.Drawing.Size(478, 79);
this.ResultLabel.TabIndex = 2;
this.ResultLabel.Text = "&Вставьте любое целочисленное значение в поле выше и нажмите кнопку \"Вычислить\", " +
"чтобы увидеть результат...";
this.ResultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// CalculateButton
//
this.CalculateButton.Location = new System.Drawing.Point(12, 116);
this.CalculateButton.Name = "CalculateButton";
this.CalculateButton.Size = new System.Drawing.Size(234, 23);
this.CalculateButton.TabIndex = 3;
this.CalculateButton.Text = "В&ычислить обработчиком";
this.CalculateButton.UseVisualStyleBackColor = true;
this.CalculateButton.Click += new System.EventHandler(this.CalculateButton_Click);
//
// SelectFormatterLabel
//
this.SelectFormatterLabel.AutoSize = true;
this.SelectFormatterLabel.Location = new System.Drawing.Point(12, 9);
this.SelectFormatterLabel.Name = "SelectFormatterLabel";
this.SelectFormatterLabel.Size = new System.Drawing.Size(188, 17);
this.SelectFormatterLabel.TabIndex = 4;
this.SelectFormatterLabel.Text = "В&ыберете обработчик:";
//
// SelectFormatterBox
//
this.SelectFormatterBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.SelectFormatterBox.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.SelectFormatterBox.FormattingEnabled = true;
this.SelectFormatterBox.Items.AddRange(new object[] {
"Обработчик счёта",
"Обработчик размера файла"});
this.SelectFormatterBox.Location = new System.Drawing.Point(12, 29);
this.SelectFormatterBox.Name = "SelectFormatterBox";
this.SelectFormatterBox.Size = new System.Drawing.Size(457, 25);
this.SelectFormatterBox.TabIndex = 5;
//
// calculateConvButton
//
this.calculateConvButton.Location = new System.Drawing.Point(252, 116);
this.calculateConvButton.Name = "calculateConvButton";
this.calculateConvButton.Size = new System.Drawing.Size(217, 23);
this.calculateConvButton.TabIndex = 6;
this.calculateConvButton.Text = "&Вычислить конвертером";
this.calculateConvButton.UseVisualStyleBackColor = true;
this.calculateConvButton.Click += new System.EventHandler(this.calculateConvButton_Click);
//
// CountValueTest
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(478, 222);
this.Controls.Add(this.calculateConvButton);
this.Controls.Add(this.SelectFormatterBox);
this.Controls.Add(this.SelectFormatterLabel);
this.Controls.Add(this.CalculateButton);
this.Controls.Add(this.ResultLabel);
this.Controls.Add(this.InsertDataBox);
this.Controls.Add(this.InsertDataLabel);
this.Font = new System.Drawing.Font("Courier New", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "CountValueTest";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Тест модуля форматирования строки";
this.Load += new System.EventHandler(this.CountValueTest_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Label InsertDataLabel;
private TextBox InsertDataBox;
private Label ResultLabel;
private Button CalculateButton;
private Label SelectFormatterLabel;
private ComboBox SelectFormatterBox;
private Button calculateConvButton;
}

View File

@ -1,56 +0,0 @@
using anbs_cp.Classes;
using anbs_cp.Interfaces;
namespace demo.TestForms;
public sealed partial class CountValueTest: Form
{
public CountValueTest ()
{
InitializeComponent();
}
private void CalculateButton_Click (object sender, EventArgs e)
{
if (string.IsNullOrEmpty(InsertDataBox.Text))
return;
long value = TypeConverter.StrToInt64(InsertDataBox.Text);
IValueFormatter formatter = SelectFormatterBox.SelectedIndex switch
{
0 => new CountFormatter(),
1 => new FileSizeFormatter(),
_ => new CountFormatter(),
};
ResultLabel.Text = formatter.Format(value);
}
private void CountValueTest_Load (object sender, EventArgs e)
{
SelectFormatterBox.SelectedIndex = 0;
}
private void InsertDataBox_TextChanged (object sender, EventArgs e)
{
ulong value = TypeConverter.StrToUInt64(InsertDataBox.Text);
if (value > long.MaxValue)
InsertDataBox.Text = long.MaxValue.ToString();
}
private void calculateConvButton_Click (object sender, EventArgs e)
{
if (string.IsNullOrEmpty(InsertDataBox.Text))
return;
long value = TypeConverter.StrToInt64(InsertDataBox.Text);
ResultLabel.Text = SelectFormatterBox.SelectedIndex switch
{
0 => new CountConverter(CountConverter.DefaultNames).Convert(value),
1 => new FileSizeConverter(FileSizeConverter.DefaultNames).Convert(value),
_ => new CountConverter(CountConverter.DefaultNames).Convert(value)
};
}
}

View File

@ -1,60 +0,0 @@
<root>
<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,125 +0,0 @@
namespace demo.TestForms;
sealed partial class FileHashAndMimeType
{
/// <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 ()
{
this.ResultLabel = new System.Windows.Forms.Label();
this.SelectFileLabel = new System.Windows.Forms.Label();
this.fileNameEdt = new System.Windows.Forms.TextBox();
this.ViewButton = new System.Windows.Forms.Button();
this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
this.topPanel = new System.Windows.Forms.Panel();
this.topPanel.SuspendLayout();
this.SuspendLayout();
//
// ResultLabel
//
this.ResultLabel.Dock = System.Windows.Forms.DockStyle.Fill;
this.ResultLabel.Location = new System.Drawing.Point(0, 0);
this.ResultLabel.Margin = new System.Windows.Forms.Padding(5);
this.ResultLabel.Name = "ResultLabel";
this.ResultLabel.Padding = new System.Windows.Forms.Padding(5);
this.ResultLabel.Size = new System.Drawing.Size(412, 428);
this.ResultLabel.TabIndex = 2;
this.ResultLabel.Text = "В&ыберете файл (введите ипя файла с полным путём вверху или с помощью диалога, на" +
"жав \"Обзор\")...";
this.ResultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// SelectFileLabel
//
this.SelectFileLabel.AutoSize = true;
this.SelectFileLabel.Location = new System.Drawing.Point(3, 11);
this.SelectFileLabel.Name = "SelectFileLabel";
this.SelectFileLabel.Size = new System.Drawing.Size(134, 17);
this.SelectFileLabel.TabIndex = 4;
this.SelectFileLabel.Text = "В&ыберете файл:";
//
// fileNameEdt
//
this.fileNameEdt.Location = new System.Drawing.Point(3, 38);
this.fileNameEdt.Name = "fileNameEdt";
this.fileNameEdt.Size = new System.Drawing.Size(288, 24);
this.fileNameEdt.TabIndex = 5;
this.fileNameEdt.TextChanged += new System.EventHandler(this.fileNameEdt_TextChanged);
//
// ViewButton
//
this.ViewButton.Location = new System.Drawing.Point(297, 39);
this.ViewButton.Name = "ViewButton";
this.ViewButton.Size = new System.Drawing.Size(103, 23);
this.ViewButton.TabIndex = 3;
this.ViewButton.Text = "&Обзор";
this.ViewButton.UseVisualStyleBackColor = true;
this.ViewButton.Click += new System.EventHandler(this.ViewButton_Click);
//
// openFileDialog
//
this.openFileDialog.AddToRecent = false;
this.openFileDialog.Filter = "Все файлы|*.*";
this.openFileDialog.FileOk += new System.ComponentModel.CancelEventHandler(this.openFileDialog_FileOk);
//
// topPanel
//
this.topPanel.Controls.Add(this.SelectFileLabel);
this.topPanel.Controls.Add(this.ViewButton);
this.topPanel.Controls.Add(this.fileNameEdt);
this.topPanel.Dock = System.Windows.Forms.DockStyle.Top;
this.topPanel.Location = new System.Drawing.Point(0, 0);
this.topPanel.Name = "topPanel";
this.topPanel.Size = new System.Drawing.Size(412, 74);
this.topPanel.TabIndex = 6;
//
// FileHashAndMimeType
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(412, 428);
this.Controls.Add(this.topPanel);
this.Controls.Add(this.ResultLabel);
this.Font = new System.Drawing.Font("Courier New", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FileHashAndMimeType";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Получение хэша и MIME-типа файла";
this.topPanel.ResumeLayout(false);
this.topPanel.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private Label ResultLabel;
private Label SelectFileLabel;
private TextBox fileNameEdt;
private Button ViewButton;
private OpenFileDialog openFileDialog;
private Panel topPanel;
}

View File

@ -1,44 +0,0 @@
using anbs_cp.Classes;
using anbs_cp.Extensions;
// ReSharper disable LocalizableElement
namespace demo.TestForms;
public sealed partial class FileHashAndMimeType: Form
{
public FileHashAndMimeType ()
{
InitializeComponent();
}
private void ViewButton_Click (object sender, EventArgs e)
{
openFileDialog.ShowDialog();
}
private void GetFileHashAndMimeType ()
{
if (string.IsNullOrEmpty(fileNameEdt.Text))
{
ResultLabel.Text = "Ôàéë íå âûáðàí èëè ââåä¸í íåñóùåñòâóþùèé ôàéë!";
return;
}
string fileHash = new FileHash(fileNameEdt.Text).ToString();
string fileType = FileExtension.MimeType(fileNameEdt.Text);
ResultLabel.Text =
$"Ïîëó÷åíû ñëåäóþùèå äàííûå äëÿ ôàéëà\r\n{fileNameEdt.Text}\r\nÕýø ôàéëà:\r\n{fileHash}\r\nÒèï ôàéëà:\r\n{fileType}";
}
private void openFileDialog_FileOk (object sender, System.ComponentModel.CancelEventArgs e)
{
fileNameEdt.Text = openFileDialog.FileName;
}
private void fileNameEdt_TextChanged (object sender, EventArgs e)
{
GetFileHashAndMimeType();
}
}

View File

@ -1,63 +0,0 @@
<root>
<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>
<metadata name="openFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -1,65 +0,0 @@
namespace demo.TestForms;
sealed partial class OsInfoFrm
{
/// <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 ()
{
this.textBox = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// textBox
//
this.textBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBox.Location = new System.Drawing.Point(0, 0);
this.textBox.Multiline = true;
this.textBox.Name = "textBox";
this.textBox.Size = new System.Drawing.Size(1029, 510);
this.textBox.TabIndex = 0;
//
// OsInfoFrm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1029, 510);
this.Controls.Add(this.textBox);
this.Font = new System.Drawing.Font("Courier New", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "OsInfoFrm";
this.Text = "Информация о системе";
this.Load += new System.EventHandler(this.OsInfoFrm_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private TextBox textBox;
}

View File

@ -1,27 +0,0 @@
using anbs_cp.Classes;
using anbs_cp.OsInfo.Classes;
namespace demo.TestForms;
public sealed partial class OsInfoFrm: Form
{
public OsInfoFrm ()
{
InitializeComponent();
}
private void OsInfoFrm_Load (object sender, EventArgs e)
{
textBox.Text = @"Процессор(ы) | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.Processors);
textBox.Text += @"Оперативная память | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.RAM);
textBox.Text += @"Видеокарта | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.Videos);
textBox.Text += @"Диски | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.Drives);
textBox.Text += @"Windows | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.Windows);
textBox.Text += @"Net | ";
textBox.Text += new SysTextSerializer().Serialize(OsInfo.Net);
}
}

View File

@ -1,60 +0,0 @@
<root>
<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,189 +0,0 @@
namespace demo.TestForms;
sealed partial class SampleMapperTest
{
/// <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 ()
{
this.DemoBoolEdt = new System.Windows.Forms.CheckBox();
this.DemoStringEdt = new System.Windows.Forms.TextBox();
this.DemoIntEdt = new System.Windows.Forms.NumericUpDown();
this.DemoDateTimeEdt = new System.Windows.Forms.DateTimePicker();
this.MapBtn = new System.Windows.Forms.Button();
this.ResultArea = new System.Windows.Forms.TextBox();
this.DemoStringLabel = new System.Windows.Forms.Label();
this.DemoIntLabel = new System.Windows.Forms.Label();
this.DemoDateTimeLabel = new System.Windows.Forms.Label();
this.MapModeEdit = new System.Windows.Forms.ComboBox();
this.MapModeLabel = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.DemoIntEdt)).BeginInit();
this.SuspendLayout();
//
// DemoBoolEdt
//
this.DemoBoolEdt.AutoSize = true;
this.DemoBoolEdt.Location = new System.Drawing.Point(32, 144);
this.DemoBoolEdt.Name = "DemoBoolEdt";
this.DemoBoolEdt.Size = new System.Drawing.Size(65, 25);
this.DemoBoolEdt.TabIndex = 0;
this.DemoBoolEdt.Text = "Bool";
this.DemoBoolEdt.UseVisualStyleBackColor = true;
//
// DemoStringEdt
//
this.DemoStringEdt.Location = new System.Drawing.Point(32, 42);
this.DemoStringEdt.Name = "DemoStringEdt";
this.DemoStringEdt.Size = new System.Drawing.Size(737, 29);
this.DemoStringEdt.TabIndex = 1;
//
// DemoIntEdt
//
this.DemoIntEdt.Location = new System.Drawing.Point(32, 109);
this.DemoIntEdt.Name = "DemoIntEdt";
this.DemoIntEdt.Size = new System.Drawing.Size(737, 29);
this.DemoIntEdt.TabIndex = 2;
//
// DemoDateTimeEdt
//
this.DemoDateTimeEdt.CustomFormat = "dd.MM.yyyy HH:mm:ss";
this.DemoDateTimeEdt.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
this.DemoDateTimeEdt.Location = new System.Drawing.Point(32, 193);
this.DemoDateTimeEdt.Name = "DemoDateTimeEdt";
this.DemoDateTimeEdt.Size = new System.Drawing.Size(737, 29);
this.DemoDateTimeEdt.TabIndex = 3;
//
// MapBtn
//
this.MapBtn.Location = new System.Drawing.Point(32, 306);
this.MapBtn.Name = "MapBtn";
this.MapBtn.Size = new System.Drawing.Size(737, 57);
this.MapBtn.TabIndex = 5;
this.MapBtn.Text = "СВЯЗАТЬ";
this.MapBtn.UseVisualStyleBackColor = true;
this.MapBtn.Click += new System.EventHandler(this.MapBtn_Click);
//
// ResultArea
//
this.ResultArea.Dock = System.Windows.Forms.DockStyle.Right;
this.ResultArea.Location = new System.Drawing.Point(819, 0);
this.ResultArea.Multiline = true;
this.ResultArea.Name = "ResultArea";
this.ResultArea.ReadOnly = true;
this.ResultArea.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.ResultArea.Size = new System.Drawing.Size(332, 378);
this.ResultArea.TabIndex = 6;
//
// DemoStringLabel
//
this.DemoStringLabel.AutoSize = true;
this.DemoStringLabel.Location = new System.Drawing.Point(32, 18);
this.DemoStringLabel.Name = "DemoStringLabel";
this.DemoStringLabel.Size = new System.Drawing.Size(54, 21);
this.DemoStringLabel.TabIndex = 7;
this.DemoStringLabel.Text = "String";
//
// DemoIntLabel
//
this.DemoIntLabel.AutoSize = true;
this.DemoIntLabel.Location = new System.Drawing.Point(32, 85);
this.DemoIntLabel.Name = "DemoIntLabel";
this.DemoIntLabel.Size = new System.Drawing.Size(30, 21);
this.DemoIntLabel.TabIndex = 8;
this.DemoIntLabel.Text = "Int";
//
// DemoDateTimeLabel
//
this.DemoDateTimeLabel.AutoSize = true;
this.DemoDateTimeLabel.Location = new System.Drawing.Point(32, 169);
this.DemoDateTimeLabel.Name = "DemoDateTimeLabel";
this.DemoDateTimeLabel.Size = new System.Drawing.Size(81, 21);
this.DemoDateTimeLabel.TabIndex = 9;
this.DemoDateTimeLabel.Text = "DateTime";
//
// MapModeEdit
//
this.MapModeEdit.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.MapModeEdit.FormattingEnabled = true;
this.MapModeEdit.Items.AddRange(new object[] {
"Full",
"Not null",
"Not default",
"Not null or default"});
this.MapModeEdit.Location = new System.Drawing.Point(32, 254);
this.MapModeEdit.Name = "MapModeEdit";
this.MapModeEdit.Size = new System.Drawing.Size(737, 29);
this.MapModeEdit.TabIndex = 10;
//
// MapModeLabel
//
this.MapModeLabel.AutoSize = true;
this.MapModeLabel.Location = new System.Drawing.Point(32, 230);
this.MapModeLabel.Name = "MapModeLabel";
this.MapModeLabel.Size = new System.Drawing.Size(167, 21);
this.MapModeLabel.TabIndex = 11;
this.MapModeLabel.Text = "Режим связывания:";
//
// SampleMapperTest
//
this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 21F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1151, 378);
this.Controls.Add(this.MapModeLabel);
this.Controls.Add(this.MapModeEdit);
this.Controls.Add(this.DemoDateTimeLabel);
this.Controls.Add(this.DemoIntLabel);
this.Controls.Add(this.DemoStringLabel);
this.Controls.Add(this.ResultArea);
this.Controls.Add(this.MapBtn);
this.Controls.Add(this.DemoDateTimeEdt);
this.Controls.Add(this.DemoIntEdt);
this.Controls.Add(this.DemoStringEdt);
this.Controls.Add(this.DemoBoolEdt);
this.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Margin = new System.Windows.Forms.Padding(4);
this.Name = "SampleMapperTest";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Тест класса SampleMapper";
((System.ComponentModel.ISupportInitialize)(this.DemoIntEdt)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private CheckBox DemoBoolEdt;
private TextBox DemoStringEdt;
private NumericUpDown DemoIntEdt;
private DateTimePicker DemoDateTimeEdt;
private Button MapBtn;
private TextBox ResultArea;
private Label DemoStringLabel;
private Label DemoIntLabel;
private Label DemoDateTimeLabel;
private ComboBox MapModeEdit;
private Label MapModeLabel;
}

View File

@ -1,70 +0,0 @@
using anbs_cp.Classes;
namespace demo.TestForms;
public sealed partial class SampleMapperTest: Form
{
public SampleMapperTest ()
{
InitializeComponent();
}
private void MapBtn_Click (object sender, EventArgs e)
{
Demo1Class demo1 = new()
{
DemoString = DemoStringEdt.Text,
DemoInt = (int)DemoIntEdt.Value,
DemoBool = DemoBoolEdt.Checked,
DemoDateTime = DemoDateTimeEdt.Value
};
Demo1Class demo2 = new()
{
DemoInt = 20220224,
DemoBool = true,
DemoDateTime = default
};
string serialize1 = new SysTextSerializer().Serialize(demo2);
SimpleMapper.MapMode mode = MapModeEdit.SelectedIndex switch
{
0 => SimpleMapper.MapMode.MapFull,
1 => SimpleMapper.MapMode.MapNotNull,
2 => SimpleMapper.MapMode.MapNotDefault,
3 => SimpleMapper.MapMode.MapNotNullOrDefault,
_ => SimpleMapper.MapMode.MapFull
};
SimpleMapper.MapEx(demo1, ref demo2, mode, new List<string>());
string serialize2 = new SysTextSerializer().Serialize(demo2);
// ReSharper disable once LocalizableElement
ResultArea.Text = $"Класс Demo2 до связывания:\r\n{serialize1}\r\nи после:\r\n{serialize2}";
}
}
public sealed class Demo1Class
{
public string? DemoString { get; set; }
public int DemoInt { get; set; }
public bool DemoBool { get; set; }
public DateTime DemoDateTime { get; set; }
}
public class Demo2Class
{
public string? DemoString { get; set; }
public int DemoInt { get; set; }
public bool DemoBool { get; set; }
public DateTime DemoDateTime { get; set; }
public string? DemoStringNotMapped { get; set; }
}

View File

@ -1,60 +0,0 @@
<root>
<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,125 +0,0 @@
namespace demo.TestForms;
partial class StringExtensionTest
{
/// <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 ()
{
stringInputLabel = new Label();
stringInput = new TextBox();
replaceInput = new TextBox();
replaceInputLabel = new Label();
resultLabel = new Label();
doItButton = new Button();
SuspendLayout();
//
// stringInputLabel
//
stringInputLabel.AutoSize = true;
stringInputLabel.Location = new Point(12, 9);
stringInputLabel.Name = "stringInputLabel";
stringInputLabel.Size = new Size(119, 17);
stringInputLabel.TabIndex = 0;
stringInputLabel.Text = "&Введите строку:";
//
// stringInput
//
stringInput.Location = new Point(12, 29);
stringInput.Name = "stringInput";
stringInput.Size = new Size(1005, 26);
stringInput.TabIndex = 1;
//
// replaceInput
//
replaceInput.Location = new Point(12, 89);
replaceInput.Multiline = true;
replaceInput.Name = "replaceInput";
replaceInput.Size = new Size(1005, 307);
replaceInput.TabIndex = 2;
//
// replaceInputLabel
//
replaceInputLabel.AutoSize = true;
replaceInputLabel.Location = new Point(12, 69);
replaceInputLabel.Name = "replaceInputLabel";
replaceInputLabel.Size = new Size(235, 17);
replaceInputLabel.TabIndex = 3;
replaceInputLabel.Text = "&Введите массив замен (что=чем):";
//
// resultLabel
//
resultLabel.Dock = DockStyle.Bottom;
resultLabel.Location = new Point(0, 454);
resultLabel.Name = "resultLabel";
resultLabel.Padding = new Padding(10);
resultLabel.Size = new Size(1025, 184);
resultLabel.TabIndex = 4;
resultLabel.Text = "&Введите данные и нажмите кнопку «Преобразовать», чтобы увидеть здесь резкльтат...";
//
// doItButton
//
doItButton.Location = new Point(12, 402);
doItButton.Name = "doItButton";
doItButton.Size = new Size(1005, 43);
doItButton.TabIndex = 5;
doItButton.Text = "&Преобразовать";
doItButton.UseVisualStyleBackColor = true;
doItButton.Click += doItButton_Click;
//
// StringExtensionTest
//
AutoScaleDimensions = new SizeF(9F, 17F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1025, 638);
Controls.Add(doItButton);
Controls.Add(resultLabel);
Controls.Add(replaceInputLabel);
Controls.Add(replaceInput);
Controls.Add(stringInput);
Controls.Add(stringInputLabel);
Font = new Font("XO Thames", 12F, FontStyle.Regular, GraphicsUnit.Point, 204);
FormBorderStyle = FormBorderStyle.Fixed3D;
Margin = new Padding(4, 3, 4, 3);
MaximizeBox = false;
MinimizeBox = false;
Name = "StringExtensionTest";
ShowIcon = false;
ShowInTaskbar = false;
StartPosition = FormStartPosition.CenterScreen;
Text = "Тест расширения класса string";
ResumeLayout(false);
PerformLayout();
}
#endregion
private Label stringInputLabel;
private TextBox stringInput;
private TextBox replaceInput;
private Label replaceInputLabel;
private Label resultLabel;
private Button doItButton;
}

View File

@ -1,47 +0,0 @@
using anbs_cp.Classes;
using anbs_cp.Extensions;
namespace demo.TestForms;
public partial class StringExtensionTest: Form
{
public StringExtensionTest ()
{
InitializeComponent();
}
private void doItButton_Click (object sender, EventArgs e)
{
if (stringInput.Text.IsNullOrWhiteSpace())
{
resultLabel.Text = @"Ошибка! Не заполнено поле ввода строки на замену!";
return;
}
if (replaceInput.Text.IsNullOrWhiteSpace())
{
resultLabel.Text = @"Ошибка! Не заполнено поле ввода списка замен!";
return;
}
string[] lines = replaceInput.Text.ReplaceLineEndings(";").Split(';');
KeyValueOrderedList<string> replaceList = [];
foreach (string line in lines)
{
string[] splitLine = line.Split('=');
if (splitLine.Length < 2)
continue;
string key = splitLine[0];
string value = splitLine[1];
replaceList.Add(new(key, value));
}
resultLabel.Text = stringInput.Text.Format(replaceList, StringComparison.CurrentCultureIgnoreCase);
}
}

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

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows7.0</TargetFramework> <TargetFramework>net7.0-windows</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
@ -24,7 +24,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="TestForms\FileHashAndMimeTypeTest.cs" /> <Compile Update="FileHashAndMimeTypeTest.cs">
<SubType>Form</SubType>
</Compile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,2 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp120</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp100</s:String></wpf:ResourceDictionary>

View File

@ -1,49 +0,0 @@
using anbs_cp.Classes;
using anbs_cp.Enums;
using anbs_cp.Extensions;
// KeyValueOrderedTest
void DoTest1 ()
{
Console.WriteLine("Вы выбрали тест KeyValueOrdered. В список будут по очереди добавляться данные.");
KeyValueOrderedList<string> kv = [];
Console.WriteLine("Добавляю данные: я=>Вася");
kv.Add(new("я", "Вася"));
Console.WriteLine(kv.Serialize());
Console.WriteLine("Добавляю данные: он=>Петя");
kv.Add(new("он", "Петя"));
Console.WriteLine(kv.Serialize());
Console.WriteLine("Добавляю данные: я=>Саша");
kv.Add(new("я", "Саша"));
Console.WriteLine(kv.Serialize());
Console.ReadLine();
}
// StringExtensions 1
void DoTest2 ()
{
Console.WriteLine("Вы выбрали тест StringExtensions 1. Введите предложение:");
string str = Console.ReadLine() ?? string.Empty;
Console.WriteLine($"None: {str.Transform(ETextTransform.None)}");
Console.WriteLine($"LowerCase: {str.Transform(ETextTransform.LowerCase)}");
Console.WriteLine($"UpperCase: {str.Transform(ETextTransform.UpperCase)}");
Console.WriteLine($"FirstUpper: {str.Transform(ETextTransform.FirstUpper)}");
Console.ReadLine();
}
Console.WriteLine("Выберете тест:");
if (!int.TryParse(Console.ReadLine(), out int testNum))
testNum = 0;
switch (testNum)
{
case 0:
break;
case 1:
DoTest1();
break;
case 2:
DoTest2();
break;
}

Some files were not shown because too many files have changed in this diff Show More