diff --git a/README.md b/README.md index bcc753c..73e0c3e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ # Что такое ANB Software Components Pack? -ANB Software Components Pack - набор полезных классов C#, которые расширяют возможности языка. -Они могут использоваться в приложенях для ОС Widows и серверов на базе этой ОС. +ANB Software Components Pack - набор полезных классов C#, которые расширяют возможности языка. Они могут использоваться в приложенях для ОС Widows и серверов на базе этой ОС. + +# Лицензия +MIIT + +# anbsoftware_componentspack +some classes that extend the capabilities of the C # language # Лицензия -MIIT +MIIT \ No newline at end of file diff --git a/anbs_cp/Classes/ActionError.cs b/anbs_cp/Classes/ActionError.cs new file mode 100644 index 0000000..fd6906e --- /dev/null +++ b/anbs_cp/Classes/ActionError.cs @@ -0,0 +1,63 @@ +using anbs_cp.Interfaces; + +namespace anbs_cp.Classes; + +/// +/// Класс ошибки +/// +public sealed class ActionError: IActionError +{ + /// + /// Критичность ошибки: + /// при некритичных ошибках продолжение выполнения операции возможно, + /// а при критичных -- нет + /// + public bool IsCritical { get; init; } + + /// + /// Объект ошибки + /// + public object Object { get; set; } + + /// + /// Сообщение об ошибке + /// + public string Message { get; set; } + + #region Конструкторы + /// + /// Конструктор по умолчанию + /// + public ActionError () + { + IsCritical = true; + Object = "Not Implemented"; + Message = "Not Implemented"; + } + + /// + /// Конструктор с 2 параметрами + /// + /// Сообщение + /// Критичность ошибки + public ActionError (string message, bool isCritical = true) + { + IsCritical = isCritical; + Object = ""; + Message = message; + } + + /// + /// Конструктор с 3 параметрами + /// + /// Объект ошибки + /// Сообщение + /// Критичность ошибки + public ActionError (object eObject, string message, bool isCritical = true) + { + IsCritical = isCritical; + Object = eObject; + Message = message; + } + #endregion +} \ No newline at end of file diff --git a/anbs_cp/Classes/ActionInfo.cs b/anbs_cp/Classes/ActionInfo.cs new file mode 100644 index 0000000..e2acadf --- /dev/null +++ b/anbs_cp/Classes/ActionInfo.cs @@ -0,0 +1,49 @@ +using anbs_cp.Interfaces; + +namespace anbs_cp.Classes; + +/// +/// Класс предупреждения +/// +public sealed class ActionInfo: IActionInfo +{ + #region Конструкторы + /// + /// Конструктор по умолчанию + /// + public ActionInfo () + { + IsStatusInfo = false; + Object = string.Empty; + Message = string.Empty; + } + + /// + /// Конструктор + /// + /// Объект + /// Сообщение + /// Является статусной информацией? + public ActionInfo (string eObject, string message, bool isStatus = false) + { + IsStatusInfo = isStatus; + Object = eObject; + Message = message; + } + #endregion + + #region Реализация интерфейса + /// + /// Объект + /// + public object Object { get; set; } + /// + /// Сообщение + /// + public string Message { get; set; } + /// + /// Статусная информация (например, начало работы) + /// + public bool IsStatusInfo { get; init; } + #endregion +} \ No newline at end of file diff --git a/anbs_cp/Classes/ActionState.cs b/anbs_cp/Classes/ActionState.cs new file mode 100644 index 0000000..1bba81d --- /dev/null +++ b/anbs_cp/Classes/ActionState.cs @@ -0,0 +1,337 @@ +using anbs_cp.Interfaces; + +namespace anbs_cp.Classes; + +/// +/// Состояние действия +/// +/// Обновлено 2023.11.1 +/// * Добавлен возвращаемый результат +/// +/// Обновлено 2023.01.121.1: +/// * Заменены интерфейсы IAction* на соответствующие классы +/// +public class ActionState +{ + /// + /// Конструктор по умолчанию + /// + public ActionState () + { + Info = new(); + Warnings = new(); + Errors = new(); + Value = default; + } + + /// + /// Конструктор с указанием начального значения + /// + /// Начальное значение + public ActionState (T defaultValue) + { + Info = new(); + Warnings = new(); + Errors = new(); + Value = defaultValue; + } + + /// + /// Список информации + /// + public List Info { get; } + + /// + /// Список предупреждений + /// + public List Warnings { get; } + + /// + /// Список ошибок + /// + public List Errors { get; } + + /// + /// Значение + /// + public T? Value { get; set; } + + #region Методы + + #region Очистка + /// + /// Очищает список ошибок + /// + public void ClearErrors () + { + Errors.Clear(); + Errors.TrimExcess(); + } + + /// + /// Очищает список предупреждений + /// + public void ClearWarnings () + { + Warnings.Clear(); + Warnings.TrimExcess(); + } + + /// + /// Очищает список информации + /// + public void ClearInfo () + { + Info.Clear(); + Info.TrimExcess(); + } + + /// + /// Очищает все списки + /// + public void Clear () + { + ClearInfo(); + ClearWarnings(); + ClearErrors(); + } + #endregion + + #region Добавление ошибки + /// + /// Добавление ошибки + /// + /// Ошибка + // ReSharper disable once MemberCanBeMadeStatic.Global + // ReSharper disable once FunctionRecursiveOnAllPaths + public void AddError (ActionError error) => Errors.Add(error); + + /// + /// Добавляет ошибки в список + /// + /// Список ошибок + public void AddErrors(IEnumerable errors) => Errors.AddRange(errors); + + /// + /// Добавление ошибки + /// + /// Является ли ошибка критической + public void AddError (bool critical = true) + { + //Создаю ошибку + ActionError error = new("", critical); + + //Добавляю ошибку + AddError(error); + } + + /// + /// Добавление ошибки + /// + /// Сообщение об ошибке + /// Является ли ошибка критической + public void AddError (string message, bool critical = true) + { + //Создаю ошибку + ActionError error = new(message, critical); + + //Добавляю ошибку + AddError(error); + } + + /// + /// Добавление ошибки + /// + /// Объект ошибки + /// Сообщение об ошибке + /// /// Является ли ошибка критической + public void AddError (string errorObject, string message, bool critical = true) + { + //Создаю ошибку + ActionError error = new(errorObject, message, critical); + + //Добавляю ошибку + AddError(error); + } + #endregion + + #region Добавление предупреждения + /// + /// Добавление предупреждения + /// + /// Предупреждение + public void AddWarning (ActionWarning warning) => Warnings.Add(warning); + + /// + /// Добавление предупреждений + /// + /// Список предупреждений + public void AddWarnings(IEnumerable warnings) => Warnings.AddRange(warnings); + + /// + /// Добавление предупреждение + /// + /// Текст предупреждения + /// Объект предупреждения + public void AddWarning (string message, string warningObject = "") + { + //Создаю предупреждение + ActionWarning warning = new(warningObject, message); + + //Добавляю предупреждение + AddWarning(warning); + } + #endregion + + #region Добавление информации + /// + /// Добавление информации + /// + /// Информация + public void AddInfo (ActionInfo info) => Info.Add(info); + + /// + /// Добавление информации + /// + /// Список информации + public void AddInfos (IEnumerable infos) => Info.AddRange(infos); + + /// + /// Добавление информации + /// + /// Текст информации + /// Объект информации + public void AddInfo (string message, string infoObject = "") + { + //Создаю информацию + ActionInfo info = new(infoObject, message); + + //Добавляю информацию + AddInfo(info); + } + #endregion + + #region Печать + /// + /// Печать списка ошибок + /// + /// Формат списка + /// Формат элемента списка + /// Список ошибок в текстовой форме + public string PrintErrorList (string formatList, string formatItem) + { + string elements = +#pragma warning disable CS8625 + Errors.Aggregate(null, (current, error) => current + error.PrintMessage(formatItem)); +#pragma warning restore CS8625 + + return string.Format(formatList, elements); + } + + /// + /// Печать списка предупреждений + /// + /// Формат списка + /// Формат элемента списка + /// Список предупреждений в текстовой форме + public string PrintWarningList (string formatList, string formatItem) + { + string elements = +#pragma warning disable CS8625 + Warnings.Aggregate(null, +#pragma warning restore CS8625 + (current, warning) => current + warning.PrintMessage(formatItem)); + + return string.Format(formatList, elements); + } + + /// + /// Печать списка информации + /// + /// Формат списка + /// Формат элемента списка + /// Список информации в текстовой форме + public string PrintInfoList (string formatList, string formatItem) + { + string elements = +#pragma warning disable CS8625 + Info.Aggregate(null, (current, info) => current + info.PrintMessage(formatItem)); +#pragma warning restore CS8625 + + return string.Format(formatList, elements); + } + #endregion + + #region Проверка на наличие + /// + /// Проверяет, есть ли ошибки + /// + /// Игнорировать не критические + /// Наличие ошибок + public bool HasErrors (bool ignoreNonCritical = false) => + ignoreNonCritical ? Errors.Any(static error => error.IsCritical) : Errors.Any(); + + /// + /// Проверяет, есть ли предупреждения + /// + /// Игнорировать информационные предупреждения + /// Наличие предупреждений + public bool HasWarnings (bool ignoreInformWarning = false) => ignoreInformWarning + ? Warnings.Any(static warning => !warning.IsInformWarning) + : Warnings.Any(); + + /// + /// Проверяет, есть ли сообщения + /// + /// Игнорировать статусные сообщения + /// Наличие сообщений + public bool HasInfo (bool ignoreStatus) => ignoreStatus ? Info.Any(static info => !info.IsStatusInfo) : Info.Any(); + + /// + /// Успешно ли завершилось + /// + public bool IsSuccess (bool ignoreNonCriticalErrors = false) => + !HasErrors(ignoreNonCriticalErrors) && !HasWarnings(true); + #endregion + + #region Количество сообщений + /// + /// Количество ошибок + /// + /// Игнорировать не критические + /// Количество ошибок + public int ErrorsCount (bool ignoreNonCritical = false) => + ignoreNonCritical ? Errors.Count(static error => error.IsCritical) : Errors.Count; + + /// + /// Количество предупреждений + /// + /// Игнорировать информационные предупреждения + /// Количество предупреждений + public int WarningsCount (bool ignoreInformWarning = false) => ignoreInformWarning + ? Warnings.Count(static warning => !warning.IsInformWarning) + : Warnings.Count; + + /// + /// Количество информационных сообщений + /// + /// Игнорировать статусные сообщения + /// Количество информационных сообщений + public int InfoCount (bool ignoreStatus) => ignoreStatus ? Info.Count(static info => !info.IsStatusInfo) : Info.Count; + #endregion + + #region Добавление другого состояния + + /// + /// Добавляет другое состояние (например, результат другого действия, который возвращает ). + /// + /// Запись состояния + public void AddState(ActionState state) + { + AddErrors(state.Errors); + AddWarnings(state.Warnings); + AddInfos(state.Info); + } + #endregion + #endregion +} \ No newline at end of file diff --git a/anbs_cp/Classes/ActionStateSimply.cs b/anbs_cp/Classes/ActionStateSimply.cs new file mode 100644 index 0000000..8c73d9d --- /dev/null +++ b/anbs_cp/Classes/ActionStateSimply.cs @@ -0,0 +1,9 @@ +namespace anbs_cp.Classes; + +/// +/// Состояние действия +/// +/// Обновлено 2023.11.1 +/// * Добавлен класс ActionState без возвращаемого значения +/// +public sealed class ActionState: ActionState { } \ No newline at end of file diff --git a/anbs_cp/Classes/ActionWarning.cs b/anbs_cp/Classes/ActionWarning.cs new file mode 100644 index 0000000..e25a6c7 --- /dev/null +++ b/anbs_cp/Classes/ActionWarning.cs @@ -0,0 +1,49 @@ +using anbs_cp.Interfaces; + +namespace anbs_cp.Classes; + +/// +/// Класс предупреждения +/// +public sealed class ActionWarning: IActionWarning +{ + #region Конструкторы + /// + /// Конструктор по умолчанию + /// + public ActionWarning () + { + IsInformWarning = false; + Object = string.Empty; + Message = string.Empty; + } + + /// + /// Конструктор + /// + /// Объект + /// Сообщение + /// Является ли информирующим предупреждением + public ActionWarning (string eObject, string message, bool isInform = false) + { + IsInformWarning = isInform; + Object = eObject; + Message = message; + } + #endregion + + #region Реализация интерфейса + /// + /// Объект + /// + public object Object { get; set; } + /// + /// Сообщение + /// + public string Message { get; set; } + /// + /// Информирующее предупреждение возникает для предупреждения ВОЗМОЖНОЙ ошибки в дальнейшей эксплуатации и не влияет на текущую операцию. + /// + public bool IsInformWarning { get; init; } + #endregion +} \ No newline at end of file diff --git a/anbs_cp/Classes/ConsoleParamsParser.cs b/anbs_cp/Classes/ConsoleParamsParser.cs new file mode 100644 index 0000000..f932b55 --- /dev/null +++ b/anbs_cp/Classes/ConsoleParamsParser.cs @@ -0,0 +1,61 @@ +namespace anbs_cp.Classes; + +/// +/// Обработчик параметров консоли +/// +public sealed class ConsoleParamsParser +{ + /// + /// Массив параметров + /// + private readonly List<(string, string?)> _paramsList; + + /// + /// Конструктор + /// + /// Параметры консоли + public ConsoleParamsParser (string[] consoleParams) + { + //Создаю список параметров + _paramsList = new(); + + //Заполняю его + foreach (string consoleParam in consoleParams) + { + //Индекс знака "=" + int eqPlace = consoleParam.IndexOf('='); + + //Получаю параметр + string param = eqPlace > -1 ? consoleParam[..eqPlace] : consoleParam; + + //Получаю значение параметра + string? value = eqPlace == -1 ? null : consoleParam[(eqPlace + 1)..].Trim(new[] { '"' }); + + //Сохраняю в списке + _paramsList.Add((param.ToLower(), value)); + } + } + + /// + /// Проверяет наличие параметра + /// + /// Параметр + /// Есть ли параметр в списке + public bool HasParam (string param) => + _paramsList.Any(keyValue => keyValue.Item1 == param.ToLower()); + + /// + /// Получает значение параметра + /// + /// + /// + public string? GetValue (string param) => + !HasParam(param) ? null : _paramsList.FirstOrDefault(keyValue => keyValue.Item1 == param.ToLower()).Item2; + + /// + /// Получает список всех параметров + /// + /// Список всех параметров + public List GetParamsList () => + _paramsList.Select(static keyValue => keyValue.Item1.ToLower()).ToList(); +} \ No newline at end of file diff --git a/anbs_cp/Classes/CountConverter.cs b/anbs_cp/Classes/CountConverter.cs new file mode 100644 index 0000000..662af0b --- /dev/null +++ b/anbs_cp/Classes/CountConverter.cs @@ -0,0 +1,21 @@ +namespace anbs_cp.Classes; + +/// +/// Конвертер количества элементов +/// +public sealed class CountConverter : ValueConverter +{ + /// + /// Имена размеров файлов по умолчанию + /// + public static readonly string[] DefaultNames = {"", "тыс.", "млн."}; + + /// + /// Конструктор класса + /// + /// Массив имён размерностей + /// Знаков после запятой (0, 1, 2) + public CountConverter (string[] valueNames, byte decimalPlace = 0) : base(valueNames, 1000, decimalPlace) + { + } +} diff --git a/anbs_cp/Classes/CountFormatter.cs b/anbs_cp/Classes/CountFormatter.cs new file mode 100644 index 0000000..29774e0 --- /dev/null +++ b/anbs_cp/Classes/CountFormatter.cs @@ -0,0 +1,50 @@ +using anbs_cp.Interfaces; + +namespace anbs_cp.Classes; + +/// +/// Форматирует число элементов в понятную строку +/// +public sealed class CountFormatter : IValueFormatter +{ + #region Cвойства класса + + /// + /// Имена чисел (тысяч, миллионов, миллиардов и т.п.) + /// + public string[] CountNames { get; set; } = { "", "тыс.", "млн.", "млрд." }; + + /// + /// Знаков после запятой + /// + public byte DecimalPlaces { get; set; } = 1; + + /// + /// Делители чисел + /// + public long[] Delimeters { get; set; } = { 1000, 1000000, 1000000000 }; + + #endregion + + #region Реализация интерфейса + + /// + /// Реализация интерфейса + /// + public string[] ValueNames + { + get => CountNames; + set => CountNames = value; + } + + /// + /// Реализация интерфейса + /// + public long[] MaxSizes + { + get => Delimeters; + set => Delimeters = value; + } + + #endregion +} \ No newline at end of file diff --git a/anbs_cp/Classes/Encrypt/StringEncrypt.cs b/anbs_cp/Classes/Encrypt/StringEncrypt.cs new file mode 100644 index 0000000..1a96540 --- /dev/null +++ b/anbs_cp/Classes/Encrypt/StringEncrypt.cs @@ -0,0 +1,37 @@ +namespace anbs_cp.Classes.Encrypt; + +/// +/// Статическая обертка для класса шифровки строк StringEncryptor +/// +public static class StringEncrypt +{ + /// + /// Метод для шифрования строки + /// + /// Строка, которая должна быть зашифрована + /// Ключ + /// Этот статический метод возвращает зашифрованную строку + public static string Encrypt (string text, string key) => new StringEncryptor().Encrypt(text, key); + + /// + /// Метод для дешифрования строки + /// + /// Строка, которая должна быть дешифрована + /// Ключ + /// Этот статический метод возвращает дешифрованную строку + public static string Decrypt (string text, string key) => new StringEncryptor().Decrypt(text, key); + + /// + /// Декодирует зашифрованную строку в HTML-пригодный формат + /// + /// Зашифрованная строка + /// Этот статический метод возвращает дешифрованную строку + public static string Base64UrlEncode (string text) => new StringEncryptor().Base64UrlEncode(text); + + /// + /// Раскодирует из декодированной строки в HTML-пригодный формат + /// + /// Декодированная строка + /// Этот статический метод возвращает шифрованную строку + public static string Base64UrlDecode (string text) => new StringEncryptor().Base64UrlDecode(text); +} \ No newline at end of file diff --git a/anbs_cp/Classes/Encrypt/StringEncryptor.cs b/anbs_cp/Classes/Encrypt/StringEncryptor.cs new file mode 100644 index 0000000..4f6cce8 --- /dev/null +++ b/anbs_cp/Classes/Encrypt/StringEncryptor.cs @@ -0,0 +1,127 @@ +using System.Security.Cryptography; +using System.Text; + +using anbs_cp.Interfaces; + +namespace anbs_cp.Classes.Encrypt; + +/// +/// Класс для шифровки строк +/// +public sealed class StringEncryptor: IEncryptor +{ + /// + /// Получение ключа из строки + /// + /// Ключ-строка + /// Хэш-ключ + /// Ключ + private static byte[] KeyFromString (string s, byte[] salt) + { + // Создаю хэшер + using Rfc2898DeriveBytes hasher = new(s, salt, 1000, HashAlgorithmName.SHA256); + + // Получаю ключ + return hasher.GetBytes(32); + } + + /// + /// Метод для шифрования строки + /// + /// Строка, которая должна быть зашифрована + /// Ключ + /// Этот метод возвращает зашифрованную строку + public string Encrypt (string value, string salt) + { + // Создаю криптограф + using Aes aes = Aes.Create(); + + // Получаю ключ + aes.Key = KeyFromString(salt, aes.IV); + + // Открываю поток + using MemoryStream ms = new(); + + // Пишу данные в поток + ms.Write(aes.IV); + + // Создаю шифрованный поток + using (CryptoStream cs = new(ms, aes.CreateEncryptor(), CryptoStreamMode.Write, true)) + // Пишу данные в него + cs.Write(Encoding.UTF8.GetBytes(value)); + + // Возвращаю зашифрованный текст + return Convert.ToBase64String(ms.ToArray()); + } + + /// + /// Метод для дешифрования строки + /// + /// Строка, которая должна быть дешифрована + /// Ключ + /// Этот метод возвращает дешифрованную строку + public string Decrypt (string encryptedValue, string salt) + { + // Открываю поток в памяти + using MemoryStream ms = new(Convert.FromBase64String(encryptedValue)); + + // Задаю ключ + byte[] iv = new byte[16]; + + // Читаю его + _ = ms.Read(iv); + + // Создаю криптограф + using Aes aes = Aes.Create(); + + // Получаю ключ + aes.Key = KeyFromString(salt, iv); + + // присваиваю ключ + aes.IV = iv; + + // Создаю поток дешифратора + using CryptoStream cs = new(ms, aes.CreateDecryptor(), CryptoStreamMode.Read, true); + + // Задаю поток итогового текста + using MemoryStream output = new(); + + // Копирую данные в выходной поток + cs.CopyTo(output); + + // Вывожу расшифрованный текст + return Encoding.UTF8.GetString(output.ToArray()); + } + + /// + /// Декодирует зашифрованную строку в HTML-пригодный формат + /// + /// Зашифрованная строка + /// Этот метод возвращает дешифрованную строку + public string Base64UrlEncode (string text) => text.TrimEnd('=').Replace('+', '-').Replace('/', '_'); + + /// + /// Раскодирует из декодированной строки в HTML-пригодный формат + /// + /// Декодированная строка + /// Этот метод возвращает шифрованную строку + public string Base64UrlDecode (string text) + { + // Первоначальная замена + string result = text.Replace('_', '/').Replace('-', '+'); + + // Заменяю значения + switch (result.Length % 4) + { + case 2: + result += "=="; + break; + case 3: + result += "="; + break; + } + + // Возвращаю результат + return result; + } +} \ No newline at end of file diff --git a/anbs_cp/Classes/Exceptions/RenameException.cs b/anbs_cp/Classes/Exceptions/RenameException.cs new file mode 100644 index 0000000..e8eb5d5 --- /dev/null +++ b/anbs_cp/Classes/Exceptions/RenameException.cs @@ -0,0 +1,37 @@ +namespace anbs_cp.Classes.Exceptions; + +/// +/// Класс-исключение для переименования папок/файлов +/// +public sealed class RenameException : Exception +{ + /// + /// Имя файла/папки + /// + public string FileName { get; } + + /// + /// Описание ошибки + /// + public string? ErrorMessage { get; } + + /// + /// Конструктор + /// + /// Имя файла/папки + /// Описание ошибки + public RenameException(string fileName, string? errorMessage) : base(GetMessage(fileName, errorMessage ?? string.Empty)) + { + FileName = fileName; + ErrorMessage = errorMessage; + } + + /// + /// Получение текстового представление ошибки + /// + /// Имя файла/папки + /// Описание ошибки + /// Текстовое представление ошибки + private static string GetMessage(string fileName, string errorMessage) => + $"При переименовании файла/папки {fileName} возникла следующая ошибка: {errorMessage}"; +} \ No newline at end of file diff --git a/anbs_cp/Classes/FileExtensions.cs b/anbs_cp/Classes/FileExtensions.cs new file mode 100644 index 0000000..2988845 --- /dev/null +++ b/anbs_cp/Classes/FileExtensions.cs @@ -0,0 +1,27 @@ +namespace anbs_cp.Classes; + +/// +/// Класс -- расширение для класса File +/// +public static class FileExtension +{ + /// + /// Получает MIME-тип файла + /// + /// Имя файла + /// MIME-тип файла + public static string MIMEType (string filename) => + MimeTypes.GetMimeType(filename); + + /// + /// Размер файла в байтах + /// + /// Полное имя и путь к файлу + /// Размер файла в байтах + public static long FileSize(string fileName) + { + FileInfo fileInfo = new (fileName); + + return fileInfo.Length; + } +} \ No newline at end of file diff --git a/anbs_cp/Classes/FileHash.cs b/anbs_cp/Classes/FileHash.cs new file mode 100644 index 0000000..72b09da --- /dev/null +++ b/anbs_cp/Classes/FileHash.cs @@ -0,0 +1,52 @@ +using System.Security.Cryptography; +using System.Text; + +namespace anbs_cp.Classes; + +/// +/// Класс для работы с хэшем файла +/// +public sealed class FileHash +{ + /// + /// Получение md5-хэша файла. + /// Взято с https://stackoverflow.com/a/24031467/16469671 + /// + /// Имя файла + /// Массив хэша + public FileHash (string fileName) + { + using MD5 md5 = MD5.Create(); + using FileStream stream = File.OpenRead(fileName); + Hash = md5.ComputeHash(stream); + } + + /// + /// Простой конструктор + /// + public FileHash () + { + Hash = new byte[] { }; + } + + /// + /// Хэш файла + /// + public byte[] Hash { get; private set; } + + /// + /// Вывод в строку + /// + /// Строка хэша файла + public override string ToString () => BitConverter.ToString(Hash).Replace("-", "").ToLowerInvariant(); + + /// + /// Конвертирует строку в хэш + /// + /// Строка + public void FromString (string value) + { + UTF8Encoding utf8 = new(); + Hash = utf8.GetBytes(value); + } +} \ No newline at end of file diff --git a/anbs_cp/Classes/FileSizeConverter.cs b/anbs_cp/Classes/FileSizeConverter.cs new file mode 100644 index 0000000..5aa77ec --- /dev/null +++ b/anbs_cp/Classes/FileSizeConverter.cs @@ -0,0 +1,21 @@ +namespace anbs_cp.Classes; + +/// +/// Конвертер размеров файлов +/// +public sealed class FileSizeConverter : ValueConverter +{ + /// + /// Имена размеров файлов по умолчанию + /// + public static readonly string[] DefaultNames = {"байт", "Кб", "Мб", "Гб", "Тб"}; + + /// + /// Конструктор класса + /// + /// Массив имён размерностей + /// Знаков после запятой (0, 1, 2) + public FileSizeConverter (string[] valueNames, byte decimalPlace = 2) : base(valueNames, 1024, decimalPlace) + { + } +} diff --git a/anbs_cp/Classes/FileSizeFormatter.cs b/anbs_cp/Classes/FileSizeFormatter.cs new file mode 100644 index 0000000..b3e2891 --- /dev/null +++ b/anbs_cp/Classes/FileSizeFormatter.cs @@ -0,0 +1,71 @@ +using anbs_cp.Interfaces; + +namespace anbs_cp.Classes; + +/// +/// Форматирует размер файла/папки в понятную строку +/// +public class FileSizeFormatter : IValueFormatter +{ + #region Cвойства класса + + /// + /// Имена размеров (байт, килобайт, мегабайт, гигабайт и террабайт) + /// + public string[] SizeNames { get; set; } = { "Байт", "Кб", "Мб", "Гб", "Тб" }; + + /// + /// Знаков после запятой + /// + public byte DecimalPlaces { get; set; } = 2; + + /// + /// Максимально байт (далее идут Кбайты) + /// + public long ByteMax { get; set; } = 1024; + + /// + /// Максимально Кбайт (далее идут Мбайты) + /// + public long KByteMax { get; set; } = 1048576; + + /// + /// Максимально Мбайт (далее идут Гбайты) + /// + public long MByteMax { get; set; } = 1073741824; + + /// + /// Максимально Гбайт (далее идут Тбайты) + /// + public long GByteMax { get; set; } = 1099511627776; + + #endregion + + #region Реализация интерфейса + + /// + /// Реализация интерфейса + /// + public string[] ValueNames + { + get => SizeNames; + set => SizeNames = value; + } + + /// + /// Реализация интерфейса + /// + public long[] MaxSizes + { + get => new[] { ByteMax, KByteMax, MByteMax, GByteMax }; + set + { + ByteMax = value[0]; + KByteMax = value[1]; + MByteMax = value[2]; + GByteMax = value[3]; + } + } + + #endregion +} \ No newline at end of file diff --git a/anbs_cp/Classes/KeyValueList.cs b/anbs_cp/Classes/KeyValueList.cs new file mode 100644 index 0000000..f9e0810 --- /dev/null +++ b/anbs_cp/Classes/KeyValueList.cs @@ -0,0 +1,163 @@ +using System.Collections; + +using anbs_cp.Structs; + +namespace anbs_cp.Classes; + +/// +/// Список из пара ключ-значение +/// +/// Тип ключа +/// Тип значения +public class KeyValueList: IEnumerable> +{ + /// + /// Хранение значений + /// + private readonly List> _list; + + #region Конструкторы + /// + /// Конструктор по умолчанию + /// + public KeyValueList () => _list = new(); + #endregion + + #region Свойства + /// + /// Список ключей из списка + /// + public IEnumerable Keys => GetKeys(); + #endregion + + #region Методы + + /// + /// Получает список ключей + /// + /// Список ключей + private IEnumerable GetKeys () => from keyValue in _list where keyValue.Key is not null select keyValue.Key; + + /// + /// Добавляет в список параметр + /// + /// Параметр + public void Add (KeyValue keyValue) => _list.Add(keyValue); + + /// + /// Добавляет в список параметр + /// + /// Ключ параметра + /// Значение + public void Add (TK key, TV value) => _list.Add(new(key, value)); + + /// + /// Изменяет значение + /// + /// Новое значение + public void ChangeValue (KeyValue keyValue) + { + // Если такой ключ не существует + if (!Contains(keyValue.Key!)) + { + // - тогда добавляю новое значение + Add(keyValue); + + // - прерываю + return; + } + + // Существующее значение + KeyValue existValue = GetItem(keyValue.Key!) ?? new(); + + // Удаляем существующее + _list.Remove(existValue); + + // Добавляем новое + _list.Add(keyValue); + } + + /// + /// Изменяет значение + /// + /// Ключ + /// Новое значение + public void ChangeValue (TK key, TV newValue) => ChangeValue(new(key, newValue)); + + /// + /// Получает элемент по ключу + /// + /// Ключ + /// Элемент + public KeyValue? GetItem (TK key) + { + // Ищем элемент в списке + foreach (KeyValue keyValueItem in _list.Where(keyValueItem => keyValueItem.Key!.Equals(key))) + // - возвращаем его при нахождении + return keyValueItem; + + // Элемент не найден -- вывожу null + return null; + } + + /// + /// Получает значение + /// + /// Ключ + /// Значение + public TV? GetValue (TK key) + { + // Если такой ключ не существует + if (!Contains(key)) + // Тогда возвращаю значение по умолчанию + return default; + + // Получаю элемент + KeyValue keyValue = GetItem(key) ?? new(); + + // Вывожу значение + return keyValue.Value; + } + + /// + /// Удаляет элемент из списка + /// + /// Элемент + public void Remove (KeyValue keyValue) => _list.Remove(keyValue); + + /// + /// Удаляет элемент из списка + /// + /// Ключ элемента + public void Remove (TK key) => Remove(GetItem(key) ?? new()); + + /// + /// Проверяет, содержится ли элемент в списке + /// + /// Элемент + /// Результат проверки + public bool Contains (KeyValue keyValue) => _list.Contains(keyValue); + + /// + /// Проверяет, содержится ли элемент в списке + /// + /// Ключ элемента + /// Результат проверки + public bool Contains (TK key) => Keys.Any(keyParam => keyParam!.Equals(key)); + + #endregion + + #region Реализация интерфейса IEnumerable> + /// + /// Получаю + /// + /// + public IEnumerator> GetEnumerator () => _list.GetEnumerator(); + + /// + /// Получаю + /// + /// + IEnumerator IEnumerable.GetEnumerator () => GetEnumerator(); + #endregion +} \ No newline at end of file diff --git a/anbs_cp/Classes/LikeDelphi.cs b/anbs_cp/Classes/LikeDelphi.cs new file mode 100644 index 0000000..09a8afc --- /dev/null +++ b/anbs_cp/Classes/LikeDelphi.cs @@ -0,0 +1,147 @@ +using anbs_cp.Classes.Exceptions; +using anbs_cp.Enums; + +namespace anbs_cp.Classes; + +/// +/// Класс, добавляющий реализацию некоторых методов Delphi, которые упрощают работу в C#. +/// +public static class LikeDelphi +{ + /// + /// Аналог функции IncludeTrailingBackslash + /// + /// Путь, к которому нужно добавить slash + /// Путь со slash в конце + public static string IncludeTrailingBackslash (string path) + { + //По умолчанию сохраняем путь + string result = path; + + //Если последний символ не "\", то добавим "\" в конце + if (path[^1] != '\\') + result = $@"{path}\"; + + //Вернём результат + return result; + } + + /// + /// Парсер строки в множество строк + /// + /// Строка, которую нужно разбить + /// Символ-делитель строки + /// Массив строк + public static List ParseString (string str, char delimiter) => str.Split(delimiter).ToList(); + + /// + /// Переименовываю файл + /// + /// Старое имя файла (с полным путём) + /// Новое имя файла (с полным путём) + /// Что делать, если существует + /// Если имеет значение RaiseException, то генерируется ошибка переименования файла + public static void RenameFile (string oldName, string newName, + EOnExistAction ifExist = EOnExistAction.RaiseException) + { + //Если целевой файл существует + if (File.Exists(newName)) + switch (ifExist) + { + //Возбуждать исключение + case EOnExistAction.RaiseException: + throw new RenameException(newName, "Файл уже существует!"); + //Прерываю + case EOnExistAction.Abort: + return; + //Игнорирую и перезаписываю файл + case EOnExistAction.Ignore: + break; + //Только для папок (для файлов равносилен RaiseException) + case EOnExistAction.RaiseExceptionIfNotEmpty: + throw new RenameException(newName, "Файл уже существует!"); + //Только для папок (для файлов равносилен Abort) + case EOnExistAction.AbortIfNotEmpty: + return; + //по умолчанию - RaiseException + default: + throw new RenameException(newName, "Файл уже существует!"); + } + + //Перемещаю файл + File.Move(oldName, newName, true); + + //Если начальный файл существует + if (File.Exists(oldName)) + //- удаляю его + File.Delete(oldName); + } + + /// + /// Удаление папки + /// + /// Папка + public static void RemoveDir (string dir) => Directory.Delete(dir, true); + + /// + /// Проверяет папку на пустоту + /// Оригинальный ответ от OwenGlendower (https://www.cyberforum.ru/windows-forms/thread1995240.html) + /// + /// Проверяемая папка + /// Пуста (true) или не пуста (false) папка + public static bool IsDirEmpty (string dir) => !Directory.EnumerateFiles(dir, "*.*", SearchOption.AllDirectories).Any(); + + /// + /// Переименовывает папку + /// + /// Старое имя папки (с полным путём) + /// Новое имя папки (с полным путём) + /// Что делать, если существует + /// Если имеет значение RaiseException, то генерируется ошибка переименования папки + public static void RenameDir (string oldName, string newName, + EOnExistAction ifExist = EOnExistAction.RaiseException) + { + //Если целевая папка существует + if (Directory.Exists(newName)) + { + switch (ifExist) + { + //Возбуждать исключение + case EOnExistAction.RaiseException: + throw new RenameException(newName, "Папка уже существует!"); + //Прерывать + case EOnExistAction.Abort: + return; + //Игнорировать и перезаписывать папку + case EOnExistAction.Ignore: + break; + //Возбуждать исключение, если не пустая + case EOnExistAction.RaiseExceptionIfNotEmpty: + if (!IsDirEmpty(newName)) + throw new RenameException(newName, "Папка уже существует и не пуста!"); + + break; + //Прерывать, если не пустая + case EOnExistAction.AbortIfNotEmpty: + if (!IsDirEmpty(newName)) + return; + + break; + //по умолчанию - RaiseException + default: + throw new RenameException(newName, "Папка уже существует!"); + } + + //Удаляю целевую папку + RemoveDir(newName); + } + + //Перемещаю папку + Directory.Move(oldName, newName); + + //Если начальная папка существует + if (Directory.Exists(oldName)) + //- удаляю его + RemoveDir(oldName); + } +} \ No newline at end of file diff --git a/anbs_cp/Classes/PasswordOptions.cs b/anbs_cp/Classes/PasswordOptions.cs new file mode 100644 index 0000000..519f5de --- /dev/null +++ b/anbs_cp/Classes/PasswordOptions.cs @@ -0,0 +1,50 @@ +namespace anbs_cp.Classes; + +/// +/// Параметры пароля +/// +public sealed class PasswordOptions +{ + /// + /// Конструктор + /// + public PasswordOptions () + { + RequiredLength = 8; + RequireLowercase = true; + RequireUppercase = true; + RequireDigit = true; + RequireNonAlphanumeric = false; + RequiredUniqueChars = 6; + } + + /// + /// Требуемая длина пароля + /// + public byte RequiredLength { get; set; } + + /// + /// Требовать строчные буквы в пароле + /// + public bool RequireLowercase { get; set; } + + /// + /// Требовать прописные буквы в пароле + /// + public bool RequireUppercase { get; set; } + + /// + /// Требовать цифры в пароле + /// + public bool RequireDigit { get; set; } + + /// + /// Требовать символы + /// + public bool RequireNonAlphanumeric { get; set; } + + /// + /// Уникальных символов + /// + public byte RequiredUniqueChars { get; set; } +} \ No newline at end of file diff --git a/anbs_cp/Classes/SimpleMapper.cs b/anbs_cp/Classes/SimpleMapper.cs new file mode 100644 index 0000000..6195d0f --- /dev/null +++ b/anbs_cp/Classes/SimpleMapper.cs @@ -0,0 +1,133 @@ +using System.Reflection; + +namespace anbs_cp.Classes; + +/// +/// Класс перевода одинаковых свойств из класса TF в класс T. +/// Оригинальные автор(-ы): keenthinker и Avtandil Kavrelishvili. +/// Улучшения: А. Н. Бабаев +/// URL: https://stackoverflow.com/questions/20410234/how-to-automatically-map-the-values-between-instances-of-two-different-classes-i +/// +public static class SimpleMapper +{ + /// + /// Перевод одинаковых свойств из класса F в класс TT. + /// + /// Экземпляр класса F + /// Ссылка на экземпляр класса T + /// Тип сопоставления + /// Список параметров для сопоставления + /// Класс-родитель + /// Класс-приемник + public static void MapEx(TF from, ref T to, MapMode mode, List list) + { + //Копирую поля + Type typeOfA = typeof(TF); + Type typeOfB = typeof(T); + foreach (FieldInfo fieldOfA in typeOfA.GetFields()) + { + //Проверяем выполнение условия и прерываем, если не выполняется + if (!CheckCondition(fieldOfA.Name, fieldOfA.GetValue(from), mode, list)) + continue; + + //Получаем FieldInfo для b по имени поля a + FieldInfo? fieldOfB = typeOfB.GetField(fieldOfA.Name); + + //Присваиваю поля типа B значение поля типа A + fieldOfB?.SetValue(to, fieldOfA.GetValue(from)); + } + + //Копирую свойства + foreach (PropertyInfo propertyOfA in typeOfA.GetProperties()) + { + //Проверяем выполнение условия и прерываем, если не выполняется + if (!CheckCondition(propertyOfA.Name, propertyOfA.GetValue(from), mode, list)) + continue; + + //Получаем PropertyInfo для b по имени свойства a + PropertyInfo? propertyOfB = typeOfB.GetProperty(propertyOfA.Name); + //Присваиваю свойству типа B значение свойства типа A + propertyOfB?.SetValue(to, propertyOfA.GetValue(from)); + } + } + + /// + /// Перевод одинаковых свойств из класса F в класс TT (режим "сопоставление всех параметров"). + /// + /// Параметр класса F + /// Класс-родитель + /// Класс-приемник + /// Элемент класса T + public static T Map(TF from) + { + //Создаю элемент + // ReSharper disable once NullableWarningSuppressionIsUsed + T result = (T)Activator.CreateInstance(typeof(T))!; + //Сопоставляю по принципу "сопоставление всех параметров" + MapEx(from, ref result, MapMode.MapFull, new()); + //Вывожу в результат + return result; + } + + /// + /// Проверка выполнения условия + /// + /// Имя элемента + /// Значение элемента + /// Режим проверки + /// Список игнорирования/добавления + /// + private static bool CheckCondition(string itemName, object? itemValue, MapMode mode, ICollection list) + { + //Если режим "Только список" и поля нет в списке, + //либо режим "Только не в списке" и поле есть в списке + //или режим "Только не пустые" и значение поля пустое, + //или режим "Только не по умолчанию" и значение по умолчанию + //то пропускаем + bool result = + mode switch + { + MapMode.MapFull => true, + MapMode.MapNotNull => itemValue != null, + MapMode.MapByList => list.Contains(itemName), + MapMode.MapIgnoreList => !list.Contains(itemName), + MapMode.MapNotDefault => itemValue != default, + MapMode.MapNotNullOrDefault => !Equals(itemValue, default(T)), + _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null) + }; + + //Возвращаем результат + return result; + } + + /// + /// Перечисление типов сопоставления + /// + public enum MapMode + { + /// + /// Сопоставление всех параметров + /// + MapFull = 0, + /// + /// Сопоставление не пустых параметров + /// + MapNotNull = 1, + /// + /// Сопоставление по списку + /// + MapByList = 2, + /// + /// Сопоставление исключая список + /// + MapIgnoreList = 3, + /// + /// Сопоставление параметров, которые не равны значению по умолчанию + /// + MapNotDefault = 4, + /// + /// Сопоставление не пустых параметров, которые не равны значению по умолчанию (NotNull и NotDefault одновременно) + /// + MapNotNullOrDefault = 5, + } +} \ No newline at end of file diff --git a/anbs_cp/Classes/TextFormatter.cs b/anbs_cp/Classes/TextFormatter.cs new file mode 100644 index 0000000..470fa0e --- /dev/null +++ b/anbs_cp/Classes/TextFormatter.cs @@ -0,0 +1,128 @@ +using System.Net.Mail; +using System.Text.RegularExpressions; + +namespace anbs_cp.Classes; + +/// +/// Форматирование текста +/// +public static class TextFormatter +{ + /// + /// Заменяет %МАРКЕРЫ% на их значения + /// + /// Текст сообщения + /// Словарь замен + /// Отформатированное сообщение + public static string FormatMessage (string message, Dictionary replaceDictionary) => + replaceDictionary.Aggregate(message, + static (current, item) => current.Replace($"%{item.Key}%", item.Value)); + + /// + /// Обрезает строку до указанных в параметре символов + /// + /// Текст, который нужно обрезать + /// Максимальное количество символов в тексте + /// Чем завершать обрезанный текст, если он был обрезан. Внимание расходует ! + /// Обрезанный текст + public static string GetShortText (string text, int maxLength, string endDots = "") => + text.Length < maxLength ? text : $"{text[..(maxLength - endDots.Length)]}{endDots}"; + + /// + /// Генерирует случайный пароль, удовлетворяющий параметрам . + /// Автор метода: Darkseal (https://stackoverflow.com/users/1233379/darkseal) + /// URL: https://stackoverflow.com/a/46229180/16469671 + /// + /// Объект допустимых параметров пароля, содержащий требования к надежности пароля. + /// Случайный пароль + public static string GenerateRandomPassword (PasswordOptions? options) + { + //Проверка options и установка по-умолчанию + options ??= new(); + + //Получаю массив символов + string[] randomChars = { + "ABCDEFGHJKLMNOPQRSTUVWXYZ", // прописные буквы + "abcdefghijkmnopqrstuvwxyz", // строчные буквы + "0123456789", // цифры + "~!@#$%^&*+-/.,{}[]();:|?<>='`" // символы + }; + + //Создаю объект Random + Random rand = new(Environment.TickCount); + + //Массив результатов + List chars = new(); + + //Вставляю прописные буквы + if (options.RequireUppercase) + chars.Insert(rand.Next(0, chars.Count), + randomChars[0][rand.Next(0, randomChars[0].Length)]); + + //Вставляю строчные буквы + if (options.RequireLowercase) + chars.Insert(rand.Next(0, chars.Count), + randomChars[1][rand.Next(0, randomChars[1].Length)]); + + //Вставляю цифры + if (options.RequireDigit) + chars.Insert(rand.Next(0, chars.Count), + randomChars[2][rand.Next(0, randomChars[2].Length)]); + + //Вставляю символы + if (options.RequireNonAlphanumeric) + chars.Insert(rand.Next(0, chars.Count), + randomChars[3][rand.Next(0, randomChars[3].Length)]); + + //Делаю выборку + for (int i = chars.Count; i < options.RequiredLength || chars.Distinct().Count() < options.RequiredUniqueChars; i++) + { + string rcs = randomChars[rand.Next(0, randomChars.Length)]; + chars.Insert(rand.Next(0, chars.Count), + rcs[rand.Next(0, rcs.Length)]); + } + + //Вывожу результат + return new(chars.ToArray()); + } + + /// + /// Проверяет на соответствие критерию электронной почты + /// Взято с: https://stackoverflow.com/a/1374644/16469671 + /// + /// Проверяемая строка + /// Является ли адресом электронной почты + public static bool IsValidEmail (string email) + { + string trimmedEmail = email.Trim(); + + if (trimmedEmail.EndsWith(".", StringComparison.Ordinal)) + return false; + + try + { + MailAddress addr = new(email); + return addr.Address == trimmedEmail; + } + catch + { + return false; + } + } + + /// + /// Проверяет текст на совпадение регулярному выражению по шаблону с опциями (см. ) + /// + /// Текст на проверку + /// Шаблон + /// Параметры проверки в формате (можно игнорировать, по умолчанию: ) + /// Есть ли совпадения в тексте + public static bool IsMatchRegExp (string text, string pattern, RegexOptions? options = null) + { + // Задаю настройки проверки регулярных выражений + RegexOptions regexOptions = options ?? RegexOptions.IgnoreCase; + + // Возвращаю результат + return Regex.IsMatch(text, pattern, regexOptions); + } +} \ No newline at end of file diff --git a/anbs_cp/Classes/TimestampValidator.cs b/anbs_cp/Classes/TimestampValidator.cs new file mode 100644 index 0000000..c85266a --- /dev/null +++ b/anbs_cp/Classes/TimestampValidator.cs @@ -0,0 +1,90 @@ +namespace anbs_cp.Classes; + +/// +/// Класс проверки временного интервала +/// +public static class TimestampValidator +{ + /// + /// Проверка попадания в заданный интервал (в мс) + /// + /// Временной интервал + /// Проверяемый временной интервал + /// Временная дельта в миллисекундах + /// + /// Попал ли в промежуток + + /// + /// + public static bool Validate(long timestamp, long checkedStamp, ulong deltaMs) => + new TimeSpan(timestamp) + TimeSpan.FromMilliseconds(deltaMs) > new TimeSpan(checkedStamp); + + /// + /// Проверка попадания текущего времени в заданный интервал (в мс) + /// + /// Временной интервал + /// Временная дельта в миллисекундах + /// Попадает ли текущее время в промежуток + + public static bool ValidateNow(long timestamp, ulong deltams) => + Validate(timestamp, DateTime.UtcNow.Ticks, deltams); + + /// + /// Проверка временного интервала (в сек) + /// + /// Временной интервал + /// Проверяемый временной интервал + /// Временная дельта в секундах + /// Попал ли в промежуток + public static bool ValidateFromSec(long timestamp, long checkedstamp, ulong deltasec) => + Validate(timestamp, checkedstamp, checked(deltasec * 1000UL)); + + /// + /// Проверка попадания текущего времени в заданный интервал (в сек) + /// + /// Временной интервал + /// Временная дельта в секундах + /// Попадает ли текущее время в промежуток + + public static bool ValidateFromSecNow(long timestamp, ulong deltasec) => + ValidateFromSec(timestamp, DateTime.UtcNow.Ticks, deltasec); + + /// + /// Проверка временного интервала (в мин) + /// + /// Временной интервал + /// Проверяемый временной интервал + /// Временная дельта в минутах + /// + /// Попал ли в промежуток + + /// + public static bool ValidateFromMin(long timestamp, long checkedstamp, ulong deltamin) => + Validate(timestamp, checkedstamp, checked(deltamin * 60000UL)); + + /// + /// Проверка попадания текущего времени в заданный интервал (в мин) + /// + /// Временной интервал + /// Временная дельта в минутах + /// Попадает ли текущее время в промежуток + + public static bool ValidateFromMinNow(long timestamp, ulong deltamin) => + ValidateFromMin(timestamp, DateTime.UtcNow.Ticks, deltamin); + + /// + /// Проверка временного интервала (в час) + /// + /// Временной интервал + /// Проверяемый временной интервал + /// Временная дельта в часах + /// + /// Попал ли в промежуток + + /// + public static bool ValidateFromHour(long timestamp, long checkedStamp, ulong deltaHour) => + Validate(timestamp, checkedStamp, checked(deltaHour * 3600000UL)); + + /// + /// Проверка попадания текущего времени в заданный интервал (в час) + /// + /// Временной интервал + /// Временная дельта в часах + /// Попадает ли текущее время в промежуток + + public static bool ValidateFromHourNow(long timestamp, ulong deltahr) => + ValidateFromHour(timestamp, DateTime.UtcNow.Ticks, deltahr); +} \ No newline at end of file diff --git a/anbs_cp/Classes/TypeConverter.cs b/anbs_cp/Classes/TypeConverter.cs new file mode 100644 index 0000000..06c88d3 --- /dev/null +++ b/anbs_cp/Classes/TypeConverter.cs @@ -0,0 +1,165 @@ +using System.Globalization; + +using Newtonsoft.Json; + +namespace anbs_cp.Classes; + +/// +/// Конвертер типов на манер Delphi +/// +public static class TypeConverter +{ + #region Конвертация числа в строку + + /// + /// Преобразование в + /// + /// Число + /// Значение в + public static string IntToStr (int value) => value.ToString(); + + /// + /// Преобразование в + /// + /// Число + /// Значение в + public static string IntToStr (uint value) => value.ToString(); + + /// + /// Преобразование в + /// + /// Число + /// Значение в + public static string IntToStr (long value) => value.ToString(); + + /// + /// Преобразование в + /// + /// Число + /// Значение в + public static string IntToStr (ulong value) => value.ToString(); + + /// + /// Преобразование в + /// + /// Число + /// Значение в + public static string IntToStr (byte value) => value.ToString(); + + /// + /// Преобразование в + /// + /// Число + /// Значение в + public static string DecimalToStr (decimal value) => value.ToString(CultureInfo.InvariantCulture); + + /// + /// Преобразование в + /// + /// Число + /// Значение в + public static string DoubleToStr (double value) => value.ToString(CultureInfo.InvariantCulture); + + /// + /// Преобразование в + /// + /// Значение правда/ложь + /// Значение в + public static string BoolToStr (bool value) => value.ToString(); + + /// + /// Преобразование любого типа в (сериализация) + /// + /// Тип + /// Значение типа + /// Значение в + public static string TypeToStr (T value) => JsonConvert.SerializeObject(value); + + #endregion + + #region Конвертация строки в число + + /// + /// Преобразование в + /// + /// Строка + /// Значение по умолчанию + /// Значение в + public static int StrToInt (string value, int defaultValue = 0) => + int.TryParse(value, out int result) ? result : defaultValue; + + /// + /// Преобразование в + /// + /// Строка + /// Значение по умолчанию + /// Значение в + public static uint StrToUInt (string value, uint defaultValue = 0) => + uint.TryParse(value, out uint result) ? result : defaultValue; + + /// + /// Преобразование в + /// + /// Строка + /// Значение по умолчанию + /// Значение в + public static long StrToInt64 (string value, long defaultValue = 0) => + long.TryParse(value, out long result) ? result : defaultValue; + + /// + /// Преобразование в + /// + /// Строка + /// Значение по умолчанию + /// Значение в + public static ulong StrToUInt64 (string value, ulong defaultValue = 0) => + ulong.TryParse(value, out ulong result) ? result : defaultValue; + + /// + /// Преобразование в + /// + /// Строка + /// Значение по умолчанию + /// Значение в + public static byte StrToByte (string value, byte defaultValue = byte.MinValue) => + byte.TryParse(value, out byte result) ? result : defaultValue; + + /// + /// Преобразование в + /// + /// Строка + /// Значение по умолчанию () + /// Значение в + public static decimal StrToDecimal (string value, decimal defaultValue = decimal.Zero) => + decimal.TryParse(value, out decimal result) ? result : defaultValue; + + /// + /// Преобразование в + /// + /// Строка + /// Значение по умолчанию + /// Значение в + public static double StrToDouble (string value, double defaultValue = 0) => + double.TryParse(value, out double result) ? result : defaultValue; + + /// + /// Преобразование в + /// + /// Строка + /// Значение по умолчанию + /// Значение в + public static bool StrToBool (string value, bool defaultValue = false) => + bool.TryParse(value, out bool result) ? result : defaultValue; + + /// + /// Преобразование в тип (десериализация) + /// + /// Тип + /// Строка + /// Значение по умолчанию + /// Значение в + public static T StrToType(string value, T defaultValue) => + JsonConvert.DeserializeObject(value) ?? defaultValue; + + #endregion +} \ No newline at end of file diff --git a/anbs_cp/Classes/ValueConverter.cs b/anbs_cp/Classes/ValueConverter.cs new file mode 100644 index 0000000..ca89b23 --- /dev/null +++ b/anbs_cp/Classes/ValueConverter.cs @@ -0,0 +1,87 @@ +using anbs_cp.Interfaces; + +namespace anbs_cp.Classes; + +/// +/// Абстрактный класс конвертера величин для отображения (улучшенный аналог ValueFormatter) +/// +public abstract class ValueConverter: IValueConverter +{ + /// + /// Конструктор + /// + /// Массив имён размерностей + /// Делитель + /// Число знаков после запятой + protected ValueConverter (string[] valueNames, long divider, byte decimalPlaces) + { + ValueNames = valueNames; + Divider = divider; + DecimalPlaces = (byte)(decimalPlaces < 3 ? decimalPlaces : 2); + } + + #region Реализация интерфейса + /// + /// Массив имён размерностей + /// + public string[] ValueNames { get; init; } + + /// + /// Делитель + /// + public long Divider { get; init; } + + /// + /// Знаков после запятой (0, 1, 2) + /// + public byte DecimalPlaces { get; init; } + + #endregion + + #region Методы + /// + /// Функция конвертирования в строку + /// + /// Значение + /// Конвертирование значение в строку + public string Convert (long value) + { + //Получаю разделенное значение + (decimal, int) result = DivideIt(value, 0); + + //Преобразую значение в строку + string resultValue = DecimalPlaces switch { + 0 => $"{result.Item1:F0}", + 1 => $"{result.Item1:F1}", + _ => $"{result.Item1:F2}" + }; + + //Возвращаю результат + return $"{resultValue} {ValueNames[result.Item2]}"; + } + + + /// + /// Рекурсивная функция деления + /// + /// Число + /// Счётчик вызова рекурсии + /// Число в остатке и количество вызовов рекурсии + private (decimal, int) DivideIt (decimal value, int count) + { + //Если счёт уже больше количества названий + if (count > ValueNames.Length) + return (value, count); + + //Если частное уже меньше делителя, то прерываем цикл + if (value < Divider) + return (value, count); + + //Увеличиваем счётчик... + count++; + + //... и продолжаем цикл + return DivideIt(value / Divider, count); + } + #endregion +} \ No newline at end of file diff --git a/anbs_cp/CountFormatter.cs b/anbs_cp/CountFormatter.cs deleted file mode 100644 index 05bba3a..0000000 --- a/anbs_cp/CountFormatter.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace anbs_cp -{ - /// - /// Форматирует число элементов в понятную строку - /// - public class CountFormatter : IValueFormatter - { - #region Cвойства класса - /// - /// Имена чисел (тысяч, миллионов, миллиардов и т.п.) - /// - public string[] CountNames { get; set; } = { "", "тыс.", "млн.", "млрд." }; - /// - /// Знаков после запятой - /// - public byte DecimalPlaces { get; set; } = 1; - /// - /// Делители чисел - /// - public long[] Delimeters { get; set; } = { 1000, 1000000, 1000000000 }; - #endregion - - #region Реализация интерфейса - /// - /// Реализация интерфейса - /// - public string[] ValueNames { get => CountNames; set => CountNames = value; } - /// - /// Реализация интерфейса - /// - public long[] MaxSizes { get => Delimeters; set => Delimeters = value; } - #endregion - } -} \ No newline at end of file diff --git a/anbs_cp/Enums/EOnExistAction.cs b/anbs_cp/Enums/EOnExistAction.cs new file mode 100644 index 0000000..345050d --- /dev/null +++ b/anbs_cp/Enums/EOnExistAction.cs @@ -0,0 +1,32 @@ +namespace anbs_cp.Enums; + +/// +/// Действия при операции переименования, если файл существует +/// +public enum EOnExistAction +{ + /// + /// Возбуждать исключение + /// + RaiseException = 0, + + /// + /// Прервать операцию + /// + Abort = 1, + + /// + /// Продолжить операцию + /// + Ignore = 2, + + /// + /// Возбуждать исключение, если папка не пуста (только для папок) + /// + RaiseExceptionIfNotEmpty = 3, + + /// + /// Прервать операцию, если папка не пуста (только для папок) + /// + AbortIfNotEmpty = 4 +} \ No newline at end of file diff --git a/anbs_cp/FileSizeFormatter.cs b/anbs_cp/FileSizeFormatter.cs deleted file mode 100644 index a4cbd33..0000000 --- a/anbs_cp/FileSizeFormatter.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace anbs_cp -{ - /// - /// Форматирует размер файла/папки в понятную строку - /// - public class FileSizeFormatter : IValueFormatter - { - #region Cвойства класса - /// - /// Имена размеров (байт, килобайт, мегабайт, гигабайт и террабайт) - /// - public string[] SizeNames { get; set; } = { "Байт", "Кб", "Мб", "Гб", "Тб" }; - /// - /// Знаков после запятой - /// - public byte DecimalPlaces { get; set; } = 2; - /// - /// Максимально байт (далее идут Кбайты) - /// - public long ByteMax { get; set; } = 1024; - /// - /// Максимально Кбайт (далее идут Мбайты) - /// - public long KByteMax { get; set; } = 1048576; - /// - /// Максимально Мбайт (далее идут Гбайты) - /// - public long MByteMax { get; set; } = 1073741824; - /// - /// Максимально Гбайт (далее идут Тбайты) - /// - public long GByteMax { get; set; } = 1099511627776; - #endregion - - #region Реализация интерфейса - /// - /// Реализация интерфейса - /// - public string[] ValueNames { get => SizeNames; set => SizeNames = value; } - /// - /// Реализация интерфейса - /// - public long[] MaxSizes - { - get => new long[] { ByteMax, KByteMax, MByteMax, GByteMax }; - set - { - ByteMax = value[0]; - KByteMax = value[1]; - MByteMax = value[2]; - GByteMax = value[3]; - } - } - #endregion - } -} \ No newline at end of file diff --git a/anbs_cp/IValueFormatter.cs b/anbs_cp/IValueFormatter.cs deleted file mode 100644 index 36e0d3b..0000000 --- a/anbs_cp/IValueFormatter.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace anbs_cp -{ - /// - /// Форматирует размерности в понятную строку - /// - public interface IValueFormatter - { - - #region Определения интерфейса - /// - /// Имена размерностей - /// - public string[] ValueNames { get; set; } - /// - /// Знаков после запятой - /// - public byte DecimalPlaces { get; set; } - /// - /// Максимальные размеры (массив ulong[4]) - /// - public long[] MaxSizes { get; set; } - #endregion - - #region Методы интерфейса - /// - /// Форматирование размерности - /// - /// Размерность, требующая форматирования - /// Форматированная размерность (например, 20 Мб) - public string Format(long value) - { - //Левая граница - long leftnum; - //Правая граница - long rightnum; - - for (int i = 0; i <= MaxSizes.Length; i++) - { - if (i == 0) - leftnum = 0; - else - leftnum = MaxSizes[i - 1]; - - if (i == MaxSizes.Length) - rightnum = long.MaxValue; - else - rightnum = MaxSizes[i]; - - if ((value >= leftnum) && (value < rightnum)) - return $"{FormatValue(value, leftnum)} {ValueNames[i]}"; - - } - - return value.ToString(); - } - /// - /// Деление числа на число с DecimalPlaces знаками после запятой - /// - /// Делимое число - /// Число-делитель - /// Частное (с DecimalPlaces знаками после запятой) - private string FormatValue(long dividend, long divider) - { - if (divider == 0) - { - return $"{dividend}"; - } - - long delim = 1; - - for (int i = 0; i <= DecimalPlaces; i++) - { - delim *= 10; - } - - decimal value = Math.Round((decimal)(dividend * delim / divider)) / delim; - - return $"{value}"; - } - #endregion - } -} \ No newline at end of file diff --git a/anbs_cp/Interfaces/IActionError.cs b/anbs_cp/Interfaces/IActionError.cs new file mode 100644 index 0000000..38cf7bb --- /dev/null +++ b/anbs_cp/Interfaces/IActionError.cs @@ -0,0 +1,14 @@ +namespace anbs_cp.Interfaces; + +/// +/// Интерфейс ошибки +/// +public interface IActionError : IActionStateMessage +{ + /// + /// Критичность ошибки: + /// при некритичных ошибках продолжение выполнения операции возможно, + /// а при критичных -- нет + /// + public bool IsCritical { get; init; } +} \ No newline at end of file diff --git a/anbs_cp/Interfaces/IActionInfo.cs b/anbs_cp/Interfaces/IActionInfo.cs new file mode 100644 index 0000000..c48f47c --- /dev/null +++ b/anbs_cp/Interfaces/IActionInfo.cs @@ -0,0 +1,12 @@ +namespace anbs_cp.Interfaces; + +/// +/// Интерфейс для информации по статусу +/// +public interface IActionInfo : IActionStateMessage +{ + /// + /// Статусная информация (например, начало работы) + /// + public bool IsStatusInfo { get; init; } +} \ No newline at end of file diff --git a/anbs_cp/Interfaces/IActionStateMessage.cs b/anbs_cp/Interfaces/IActionStateMessage.cs new file mode 100644 index 0000000..e6af12b --- /dev/null +++ b/anbs_cp/Interfaces/IActionStateMessage.cs @@ -0,0 +1,24 @@ +namespace anbs_cp.Interfaces; + +/// +/// Интерфейс сообщения состояния +/// +public interface IActionStateMessage +{ + /// + /// Объект сообщения + /// + public object Object { get; set; } + + /// + /// Текст сообщения + /// + public string Message { get; set; } + + /// + /// Функция вывода сообщения + /// + /// Строка-форматирование (например, «[{0}] - {1}») + /// Отформатированную строка + public string PrintMessage (string format) => string.Format (format, Object, Message); +} \ No newline at end of file diff --git a/anbs_cp/Interfaces/IActionWarning.cs b/anbs_cp/Interfaces/IActionWarning.cs new file mode 100644 index 0000000..23ec4cc --- /dev/null +++ b/anbs_cp/Interfaces/IActionWarning.cs @@ -0,0 +1,12 @@ +namespace anbs_cp.Interfaces; + +/// +/// Интерфейс предупреждения +/// +public interface IActionWarning : IActionStateMessage +{ + /// + /// Информирующее предупреждение возникает для предупреждения ВОЗМОЖНОЙ ошибки в дальнейшей эксплуатации и не влияет на текущую операцию. + /// + public bool IsInformWarning { get; init; } +} \ No newline at end of file diff --git a/anbs_cp/Interfaces/IEncryptor.cs b/anbs_cp/Interfaces/IEncryptor.cs new file mode 100644 index 0000000..4fb84ea --- /dev/null +++ b/anbs_cp/Interfaces/IEncryptor.cs @@ -0,0 +1,37 @@ +namespace anbs_cp.Interfaces; + +/// +/// Интерфейс шифрования +/// +public interface IEncryptor +{ + /// + /// Метод для шифрования строки + /// + /// Строка, которая должна быть зашифрована + /// Ключ шифрования + /// Этот метод возвращает зашифрованную строку + string Encrypt (string value, string salt); + + /// + /// Метод для дешифрования строки + /// + /// Строка, которая должна быть дешифрована + /// Ключ шифрования + /// Этот метод возвращает дешифрованную строку + string Decrypt (string encryptedValue, string salt); + + /// + /// Декодирует зашифрованную строку в HTML-пригодный формат + /// + /// Зашифрованная строка + /// Этот метод возвращает дешифрованную строку + string Base64UrlEncode (string text); + + /// + /// Раскодирует из декодированной строки в HTML-пригодный формат + /// + /// Декодированная строка + /// Этот метод возвращает шифрованную строку + string Base64UrlDecode (string text); +} \ No newline at end of file diff --git a/anbs_cp/Interfaces/IValueConverter.cs b/anbs_cp/Interfaces/IValueConverter.cs new file mode 100644 index 0000000..2400136 --- /dev/null +++ b/anbs_cp/Interfaces/IValueConverter.cs @@ -0,0 +1,22 @@ +namespace anbs_cp.Interfaces; + +/// +/// Интерфейс конвертера величин для отображения (улучшенный аналог IValueFormatter) +/// +public interface IValueConverter +{ + /// + /// Массив имён размерностей + /// + public string[] ValueNames { get; init; } + + /// + /// Делитель + /// + public long Divider { get; init; } + + /// + /// Знаков после запятой (0, 1, 2) + /// + public byte DecimalPlaces { get; init; } +} \ No newline at end of file diff --git a/anbs_cp/Interfaces/IValueFormatter.cs b/anbs_cp/Interfaces/IValueFormatter.cs new file mode 100644 index 0000000..2ae523d --- /dev/null +++ b/anbs_cp/Interfaces/IValueFormatter.cs @@ -0,0 +1,74 @@ +namespace anbs_cp.Interfaces; + +/// +/// Форматирует размерности в понятную строку +/// +public interface IValueFormatter +{ + #region Определения интерфейса + + /// + /// Имена размерностей + /// + public string[] ValueNames { get; set; } + + /// + /// Знаков после запятой + /// + public byte DecimalPlaces { get; set; } + + /// + /// Максимальные размеры (массив ulong[4]) + /// + public long[] MaxSizes { get; set; } + + #endregion + + #region Методы интерфейса + + /// + /// Форматирование размерности + /// + /// Размерность, требующая форматирования + /// Форматированная размерность (например, 20 Мб) + public string Format(long value) + { + //Левая граница + long leftnum; + //Правая граница + long rightnum; + + for (int i = 0; i <= MaxSizes.Length; i++) + { + leftnum = i == 0 ? 0 : MaxSizes[i - 1]; + + rightnum = i == MaxSizes.Length ? long.MaxValue : MaxSizes[i]; + + if (value >= leftnum && value < rightnum) + return $"{FormatValue(value, leftnum)} {ValueNames[i]}"; + } + + return value.ToString(); + } + + /// + /// Деление числа на число с DecimalPlaces знаками после запятой + /// + /// Делимое число + /// Число-делитель + /// Частное (с DecimalPlaces знаками после запятой) + private string FormatValue(long dividend, long divider) + { + if (divider == 0) return $"{dividend}"; + + long delim = 1; + + for (int i = 0; i <= DecimalPlaces; i++) delim *= 10; + + decimal value = Math.Round((decimal)(dividend * delim / divider)) / delim; + + return $"{value}"; + } + + #endregion +} \ No newline at end of file diff --git a/anbs_cp/LikeDelphi.cs b/anbs_cp/LikeDelphi.cs deleted file mode 100644 index bf6831d..0000000 --- a/anbs_cp/LikeDelphi.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -namespace anbs_cp -{ - /// - /// Класс, добавляющий реализацию некоторых методов Delphi, которые упрощают работу в C#. - /// - public static class LikeDelphi - { - /// - /// Аналог функции IncludeTrailingBackslash - /// - /// Путь, к которому нужно добавить slash - /// Путь со slash в конце - public static string IncludeTrailingBackslash(string path) - { - string result = path; - int Index = path.Length - 1; - if (path[Index] != '\\') - { - result = $"{path}\\"; - } - return result; - } - /// - /// Парсер строки в множество строк - /// - /// Строка, которую нужно разбить - /// Символ-делитель строки - /// Массив строк - public static List ParseString(string astring, char delim) - { - int from = -1; - int to; - List result = new(); - do - { - from++; - to = astring.IndexOf(delim, from); - if (to <= 0) - to = astring.Length; - if (from != to) - result.Add(astring[from..(to-from)]); - from = to; - } while (to != astring.Length); - return result; - } - } -} \ No newline at end of file diff --git a/anbs_cp/Structs/KeyValue.cs b/anbs_cp/Structs/KeyValue.cs new file mode 100644 index 0000000..ab42d49 --- /dev/null +++ b/anbs_cp/Structs/KeyValue.cs @@ -0,0 +1,51 @@ +namespace anbs_cp.Structs; + +/// +/// Пара ключ-значение +/// +/// Тип ключа +/// Тип значения +public struct KeyValue +{ + #region Конструкторы + /// + /// Конструктор по умолчанию + /// + public KeyValue () + { + Key = default; + Value = default; + } + + /// + /// Конструктор со значениями + /// + /// Ключ + /// Значение + public KeyValue (TK key, TV value) + { + Key = key; + Value = value; + } + #endregion + + #region Свойства + /// + /// Ключ + /// + public TK? Key { get; set; } + + /// + /// Значение + /// + public TV? Value { get; set; } + #endregion + + #region Методы + /// + /// Получает ключ-значение по умолчанию + /// + /// Ключ-значение по умолчанию + public static KeyValue GetDefault() => new(); + #endregion +} \ No newline at end of file diff --git a/anbs_cp/Structs/TwoDimSize.cs b/anbs_cp/Structs/TwoDimSize.cs new file mode 100644 index 0000000..1e8db7d --- /dev/null +++ b/anbs_cp/Structs/TwoDimSize.cs @@ -0,0 +1,61 @@ +namespace anbs_cp.Structs; + +/// +/// Двумерный размер +/// +public struct TwoDimSize +{ + #region Приватные поля + /// + /// Длина (приватное) + /// + private int _pWidth; + + /// + /// Высота (приватное) + /// + private int _pHeight; + #endregion + + #region Конструкторы + /// + /// Конструктор по умолчанию + /// + public TwoDimSize () + { + Width = 0; + Height = 0; + } + + /// + /// Конструктор + /// + /// Длина + /// Высота + public TwoDimSize (int width, int height) + { + Width = width; + Height = height; + } + #endregion + + #region Свойства + /// + /// Длина + /// + public int Width + { + readonly get => _pWidth; + set => _pWidth = value < 0 ? 0 : value; + } + + /// + /// Высота + /// + public int Height + { + readonly get => _pHeight; + set => _pHeight = value < 0 ? 0 : value; + } + #endregion +} \ No newline at end of file diff --git a/anbs_cp/TypeConverter.cs b/anbs_cp/TypeConverter.cs deleted file mode 100644 index 3ab4951..0000000 --- a/anbs_cp/TypeConverter.cs +++ /dev/null @@ -1,114 +0,0 @@ -namespace anbs_cp -{ - /// - /// Конвертер типов на манер Delphi - /// - public static class TypeConverter - { - #region Конвертация числа в строку - /// - /// Преобразование int в string - /// - /// Число - /// Строка - public static string IntToStr(int AInt) => AInt.ToString(); - /// - /// Преобразование uint в string - /// - /// Число - /// Строка - public static string IntToStr(uint AInt) => AInt.ToString(); - /// - /// Преобразование long в string - /// - /// Число - /// Строка - public static string IntToStr(long AInt) => AInt.ToString(); - /// - /// Преобразование ulong в string - /// - /// Число - /// Строка - public static string IntToStr(ulong AInt) => AInt.ToString(); - /// - /// Преобразование byte в string - /// - /// Число - /// Строка - public static string IntToStr(byte AInt) => AInt.ToString(); - #endregion - - #region Конвертация строки в число - /// - /// Преобразование строки в число - /// - /// Строка - /// Значение по умолчанию (по умолчанию, 0) - /// Число - public static int StrToInt(string AStr, int ADefault = 0) - { - if (!int.TryParse(AStr, out int result)) - { - result = ADefault; - } - return result; - } - /// - /// Преобразование строки в число - /// - /// Строка - /// Значение по умолчанию (по умолчанию, 0) - /// Число - public static uint StrToUInt(string AStr, uint ADefault = 0) - { - if (!uint.TryParse(AStr, out uint result)) - { - result = ADefault; - } - return result; - } - /// - /// Преобразование строки в число - /// - /// Строка - /// Значение по умолчанию (по умолчанию, 0) - /// Число - public static long StrToInt64(string AStr, long ADefault = 0) - { - if (!long.TryParse(AStr, out long result)) - { - result = ADefault; - } - return result; - } - /// - /// Преобразование строки в число - /// - /// Строка - /// Значение по умолчанию (по умолчанию, 0) - /// Число - public static ulong StrToUInt64(string AStr, ulong ADefault = 0) - { - if (!ulong.TryParse(AStr, out ulong result)) - { - result = ADefault; - } - return result; - } - /// - /// Преобразование строки в число - /// - /// Строка - /// Значение по умолчанию (по умолчанию, 0) - /// Число - public static byte StrToByte(string AStr, byte ADefault = 0) - { - if (!byte.TryParse(AStr, out byte result)) - { - result = ADefault; - } - return result; - } - #endregion - } -} \ No newline at end of file diff --git a/anbs_cp/anbs_cp.csproj b/anbs_cp/anbs_cp.csproj index 8d583a6..a6a5e8f 100644 --- a/anbs_cp/anbs_cp.csproj +++ b/anbs_cp/anbs_cp.csproj @@ -1,36 +1,51 @@ - + - net6.0 - 1.20211111.0 - Alexander Babaev - ANB Software Components Pack - Library of some useful functions in C# language. - Alexander Babaev + net8.0 + 2023.1114.0 + Александр Бабаев + Набор компонентов ANB Software + Библиотека полезных методов языка C# + Александр Бабаев anbs_cp anbs_cp enable enable True - False - https://github.com/GoodBoyAlex/anbsoftware_componentspack - https://github.com/GoodBoyAlex/anbsoftware_componentspack - 1.2021.1111 - 1.2021.1111 + True + https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack + https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack + + + ANBSoftware.ComponentsPack + MIT + 6.0 + git + True - 2 + 7 True + none - 2 + 7 True + none - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/anbs_cp/anbs_cp.csproj.DotSettings b/anbs_cp/anbs_cp.csproj.DotSettings new file mode 100644 index 0000000..632c268 --- /dev/null +++ b/anbs_cp/anbs_cp.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp120 \ No newline at end of file diff --git a/anbs_cpdb/Classes/MySqlEngine.cs b/anbs_cpdb/Classes/MySqlEngine.cs new file mode 100644 index 0000000..e280601 --- /dev/null +++ b/anbs_cpdb/Classes/MySqlEngine.cs @@ -0,0 +1,369 @@ +using anbs_cp.Database.Interfaces; + +using Dapper; + +using MySqlConnector; + +namespace anbs_cp.Database.Classes; + +public class MySqlEngine: IDbEngine +{ + /// + /// Конструктор + /// + /// Строка подключения базы данных + public MySqlEngine (string connectionString) => ConnectionString = connectionString; + + /// + /// Строка подключения базы данных + /// + public string ConnectionString { get; set; } + + #region Базовые операции + /// + /// Выполняем команду + /// + /// Запрос + /// Данные запроса + /// Количество затронутых строк + public async Task ExecuteAsync (string sql, object? values = null) + { + // Подключаемся к БД + await using MySqlConnection connection = new(ConnectionString); + + // Открываем соединение + await connection.OpenAsync(); + + // Выполняем команду и выводим результат + return await connection.ExecuteAsync(sql, values); + } + + /// + /// Выполняем команду + /// + /// Запрос + /// Данные запроса + /// Количество затронутых строк + public int Execute (string sql, object? values = null) => ExecuteAsync(sql, values).GetAwaiter().GetResult(); + + /// + /// Запрос + /// + /// Тип передаваемого значения + /// Запрос + /// Данные запроса + /// Возвращает массив типа или значение по умолчанию + public async Task> QueryAsync (string sql, object? values = null) + { + // Подключаемся к БД + await using MySqlConnection connection = new(ConnectionString); + + // Открываем соединение + await connection.OpenAsync(); + + // Выполняем запрос и выводим результат + return await connection.QueryAsync(sql, values); + } + + /// + /// Запрос + /// + /// Тип передаваемого значения + /// Запрос + /// Данные запроса + /// Возвращает массив типа или значение по умолчанию + public IEnumerable Query (string sql, object? values = null) => QueryAsync(sql, values).GetAwaiter().GetResult(); + + /// + /// Запрос строки + /// + /// Тип передаваемого значения + /// Запрос + /// Данные запроса + /// Возвращает массив типа или значение по умолчанию + public async Task QueryRowAsync (string sql, object? values = null) + { + // Подключаемся к БД + await using MySqlConnection connection = new(ConnectionString); + + // Открываем соединение + await connection.OpenAsync(); + + // Выполняем запрос и выводим результат + return await connection.QuerySingleOrDefaultAsync(sql, values); + } + + /// + /// Запрос строки + /// + /// Тип передаваемого значения + /// Запрос + /// Данные запроса + /// Возвращает массив типа или значение по умолчанию + public T? QueryRow (string sql, object? values = null) => QueryRowAsync(sql, values).GetAwaiter().GetResult(); + + #endregion + + + #region Получение данных + /// + /// Получает массив данных (SELECT * FROM...) + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Массив результата запроса + public async Task> GetResultsAsync (string sql, object? values = null) => await QueryAsync(sql, values); + + /// + /// Получает массив данных (SELECT * FROM...) + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Массив результата запроса + public IEnumerable GetResults (string sql, object? values = null) => GetResultsAsync(sql, values).GetAwaiter().GetResult(); + + /// + /// Получает строку в массиве данных + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Строки данных или null + public async Task GetRowAsync (string sql, object? values = null) + { + // Подключаемся к БД + await using MySqlConnection connection = new(ConnectionString); + + // Открываем соединение + await connection.OpenAsync(); + + // Выполняем запрос и выводим результат + return await connection.QuerySingleOrDefaultAsync(sql, values); + } + + /// + /// Получает строку в массиве данных + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Строки данных или null + public T? GetRow (string sql, object? values = null) => GetRowAsync(sql, values).GetAwaiter().GetResult(); + + /// + /// Получает колонку в массиве данных + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Колонка данных или null + public async Task> GetColAsync (string sql, object? values = null) + where T : IComparable, IConvertible, IEquatable => await QueryAsync(sql, values); + + /// + /// Получает колонку в массиве данных + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Колонка данных или null + public IEnumerable GetCol (string sql, object? values = null) where T : IComparable, IConvertible, IEquatable => + GetColAsync(sql, values).GetAwaiter().GetResult(); + + /// + /// Получение значение единичного поля + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Поле или null + public async Task GetVarAsync (string sql, object? values = null) where T : IComparable, IConvertible, IEquatable + { + // Подключаемся к БД + await using MySqlConnection connection = new(ConnectionString); + + // Открываем соединение + await connection.OpenAsync(); + + // Выполняем запрос и выводим результат + return await connection.QuerySingleOrDefaultAsync(sql, values); + } + + /// + /// Получение значение единичного поля + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Поле или null + public T? GetVar (string sql, object? values = null) where T : IComparable, IConvertible, IEquatable => + GetVarAsync(sql, values).GetAwaiter().GetResult(); + + #endregion + + #region CRUD данные + + /// + /// Вставляет данные в таблицу + /// + /// Класс данных + /// Данные + /// Имя таблицы + /// Результат выполнения + public async Task InsertAsync (T data, string tableName) where T : class + { + // Получение список имён свойств в data + List propertyNamesList = (from dataProperty in data.GetType().GetProperties() select dataProperty.Name).ToList(); + + // Получаем список имён в data, обрамленные @ + List propertyValuesList = propertyNamesList.Select(static propertyName => $"@{propertyName}").ToList(); + + //Получаем строку имён свойств + string propertyNames = string.Join(", ", propertyNamesList.ToArray()); + + // Получаем строку имён свойств, обрамленных @ + string propertyValues = string.Join(", ", propertyValuesList.ToArray()); + + // Создаю соединение + await using MySqlConnection connection = new(ConnectionString); + + // Создаю запрос + string sql = $""" + INSERT + INTO {tableName} ({propertyNames}) + VALUES ({propertyValues}) + """; + + // Выполняю запрос + return await connection.ExecuteAsync(sql, data) > 0; + } + + /// + /// Вставляет данные в таблицу + /// + /// Класс данных + /// Данные + /// Имя таблицы + /// Результат выполнения + public bool Insert (T data, string tableName) where T : class => InsertAsync(data, tableName).GetAwaiter().GetResult(); + + /// + /// Обновляет строку в таблице + /// + /// Класс данных + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + public async Task UpdateAsync (T data, string tableName, string whereConditionColumn) where T : class + { + // Получение список имён свойств в data + List propertyNamesList = (from dataProperty in data.GetType().GetProperties() + where dataProperty.Name != whereConditionColumn + select dataProperty.Name).ToList(); + + // Получаем список имён в data, обрамленные @ + List propertyKeyValuesList = propertyNamesList.Select(static propertyName => $"{propertyName}=@{propertyName}").ToList(); + + // Получаем строку имён свойств, обрамленных @ + string properties = string.Join(", ", propertyKeyValuesList.ToArray()); + + // Создаю соединение + await using MySqlConnection connection = new(ConnectionString); + + // Создаю запрос + string sql = $""" + UPDATE {tableName} + SET + {properties} + WHERE + {whereConditionColumn}=@{whereConditionColumn} + """; + + // Выполняю запрос + return await connection.ExecuteAsync(sql, data) > 0; + } + + /// + /// Обновляет строку в таблице + /// + /// Класс данных + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + public bool Update (T data, string tableName, string whereConditionColumn) where T : class => + UpdateAsync(data, tableName, whereConditionColumn).GetAwaiter().GetResult(); + + /// + /// Удаляет строки + /// + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + public async Task DeleteAsync (T data, string tableName, string whereConditionColumn) where T : class + { + // Создаю соединение + await using MySqlConnection connection = new(ConnectionString); + + // Создаю запрос + string sql = $""" + DELETE FROM + {tableName} + WHERE + {whereConditionColumn}=@{whereConditionColumn} + """; + + // Выполняю запрос + return await connection.ExecuteAsync(sql, data) > 0; + } + + /// + /// Удаляет строки + /// + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + public bool Delete (T data, string tableName, string whereConditionColumn) where T : class => + DeleteAsync(data, tableName, whereConditionColumn).GetAwaiter().GetResult(); + + /// + /// Удаляет строку + /// + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + public async Task DeleteRowAsync (T data, string tableName, string whereConditionColumn) where T : class + { + // Создаю соединение + await using MySqlConnection connection = new(ConnectionString); + + // Создаю запрос + string sql = $""" + DELETE FROM + {tableName} + WHERE + {whereConditionColumn}=@{whereConditionColumn} + LIMIT 1 + """; + + // Выполняю запрос + return await connection.ExecuteAsync(sql, data) > 0; + } + + /// + /// Удаляет строку + /// + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + public bool DeleteRow (T data, string tableName, string whereConditionColumn) where T : class => + DeleteRowAsync(data, tableName, whereConditionColumn).GetAwaiter().GetResult(); + #endregion +} \ No newline at end of file diff --git a/anbs_cpdb/Interfaces/IDbEngine.cs b/anbs_cpdb/Interfaces/IDbEngine.cs new file mode 100644 index 0000000..b4f5943 --- /dev/null +++ b/anbs_cpdb/Interfaces/IDbEngine.cs @@ -0,0 +1,221 @@ +using System.Transactions; + +namespace anbs_cp.Database.Interfaces; + +/// +/// Интерфейс для работы с базой данных +/// +public interface IDbEngine +{ + /// + /// Строка подключения + /// + string ConnectionString { get; set; } + + #region Базовые операции + + /// + /// Выполняем команду + /// + /// Запрос + /// Данные запроса + /// Количество затронутых строк + Task ExecuteAsync (string sql, object? values = null); + + /// + /// Выполняем команду + /// + /// Запрос + /// Данные запроса + /// Количество затронутых строк + int Execute (string sql, object? values = null); + + /// + /// Запрос + /// + /// Тип передаваемого значения + /// Запрос + /// Данные запроса + /// Возвращает массив типа или значение по умолчанию + Task> QueryAsync (string sql, object? values = null); + + /// + /// Запрос + /// + /// Тип передаваемого значения + /// Запрос + /// Данные запроса + /// Возвращает массив типа или значение по умолчанию + IEnumerable Query (string sql, object? values = null); + + /// + /// Запрос строки + /// + /// Тип передаваемого значения + /// Запрос + /// Данные запроса + /// Возвращает массив типа или значение по умолчанию + Task QueryRowAsync (string sql, object? values = null); + + /// + /// Запрос строки + /// + /// Тип передаваемого значения + /// Запрос + /// Данные запроса + /// Возвращает массив типа или значение по умолчанию + T? QueryRow (string sql, object? values = null); + #endregion + + #region Получение данных + + /// + /// Получает массив данных (SELECT * FROM...) + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Массив результата запроса + Task> GetResultsAsync (string sql, object? values = null); + + /// + /// Получает массив данных (SELECT * FROM...) + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Массив результата запроса + IEnumerable GetResults (string sql, object? values = null); + + /// + /// Получает строку в массиве данных + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Строки данных или null + Task GetRowAsync (string sql, object? values = null); + + /// + /// Получает строку в массиве данных + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Строки данных или null + T? GetRow (string sql, object? values = null); + + /// + /// Получает колонку в массиве данных + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Колонка данных или null + Task> GetColAsync (string sql, object? values = null) where T: IComparable, IConvertible, IEquatable; + + /// + /// Получает колонку в массиве данных + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Колонка данных или null + IEnumerable GetCol (string sql, object? values = null) where T: IComparable, IConvertible, IEquatable; + + /// + /// Получение значение единичного поля + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Поле или null + Task GetVarAsync (string sql, object? values = null) where T: IComparable, IConvertible, IEquatable; + + /// + /// Получение значение единичного поля + /// + /// Тип получаемых данных + /// SQL-запрос + /// Данные запроса + /// Поле или null + T? GetVar (string sql, object? values = null) where T: IComparable, IConvertible, IEquatable; + + #endregion + + #region CRUD данные + /// + /// Вставляет данные в таблицу + /// + /// Класс данных + /// Данные + /// Имя таблицы + /// Результат выполнения + Task InsertAsync (T data, string tableName) where T: class; + + /// + /// Вставляет данные в таблицу + /// + /// Класс данных + /// Данные + /// Имя таблицы + /// Результат выполнения + bool Insert (T data, string tableName) where T: class; + + /// + /// Обновляет строку в таблице + /// + /// Класс данных + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + Task UpdateAsync (T data, string tableName, string whereConditionColumn) where T: class; + + /// + /// Обновляет строку в таблице + /// + /// Класс данных + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + bool Update (T data, string tableName, string whereConditionColumn) where T: class; + + /// + /// Удаляет строки + /// + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + Task DeleteAsync (T data, string tableName, string whereConditionColumn) where T: class; + + /// + /// Удаляет строки + /// + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + bool Delete (T data, string tableName, string whereConditionColumn) where T: class; + + /// + /// Удаляет строку + /// + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + Task DeleteRowAsync (T data, string tableName, string whereConditionColumn) where T: class; + + /// + /// Удаляет строку + /// + /// Данные + /// Имя таблицы + /// Условие поиска строки. ВНИМАНИЕ! Должно быть одним из указанных свойств типа класса data + /// Результат выполнения + bool DeleteRow (T data, string tableName, string whereConditionColumn) where T: class; + #endregion +} \ No newline at end of file diff --git a/anbs_cpdb/anbs_cpdb.csproj b/anbs_cpdb/anbs_cpdb.csproj new file mode 100644 index 0000000..0624317 --- /dev/null +++ b/anbs_cpdb/anbs_cpdb.csproj @@ -0,0 +1,26 @@ + + + + net8.0 + enable + enable + anbs_cp_db + anbs_cp.Database + True + ANBSoftware.ComponentsPack.Database + 2023.11.14.0 + Александр Бабаев + Набор компонентов ANB Software для работы с БД + Библиотека полезных методов языка C# для работы с базами данных + Александр Бабаев + https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack + https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack + git + + + + + + + + diff --git a/anbs_cpdb/anbs_cpdb.csproj.DotSettings b/anbs_cpdb/anbs_cpdb.csproj.DotSettings new file mode 100644 index 0000000..632c268 --- /dev/null +++ b/anbs_cpdb/anbs_cpdb.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp120 \ No newline at end of file diff --git a/anbs_cpfn/Classes/NetFileExtension.cs b/anbs_cpfn/Classes/NetFileExtension.cs new file mode 100644 index 0000000..bef0227 --- /dev/null +++ b/anbs_cpfn/Classes/NetFileExtension.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Http; + +namespace anbs_cp.ForNet.Classes; + +/// +/// Класс -- расширение для класса File +/// +public class NetFileExtension +{ + /// + /// Получает MIME-тип файла + /// + /// Загружаемый файл + /// MIME-тип файла + public static string MIMEType (IFormFile file) => + file.ContentType; +} \ No newline at end of file diff --git a/anbs_cpfn/Classes/NetFileHash.cs b/anbs_cpfn/Classes/NetFileHash.cs new file mode 100644 index 0000000..fc2e50c --- /dev/null +++ b/anbs_cpfn/Classes/NetFileHash.cs @@ -0,0 +1,38 @@ +using System.Security.Cryptography; + +using anbs_cp.Classes; + +using Microsoft.AspNetCore.Http; + +namespace anbs_cp.ForNet.Classes; + +public static class NetFileHash +{ + /// + /// Получение md5-хэша загружаемого файла. + /// Взято с https://stackoverflow.com/a/67081012/16469671 + /// + /// Загружаемый файл + /// Массив хэша + public static FileHash GetFileHash (IFormFile file) + { + //Создаю md5 + using MD5 md5 = MD5.Create(); + + //Создаю поток для чтения + using StreamReader streamReader = new(file.OpenReadStream()); + + //Получаю строковый хэш + string hash = BitConverter.ToString(md5.ComputeHash(streamReader.BaseStream)).Replace("-", "") + .ToLowerInvariant(); + + //Создаю результат + FileHash fileHash = new(); + + //Вношу в него данные + fileHash.FromString(hash); + + //Возвращаю результат + return fileHash; + } +} \ No newline at end of file diff --git a/anbs_cpfn/Classes/NetTypeConverter.cs b/anbs_cpfn/Classes/NetTypeConverter.cs new file mode 100644 index 0000000..5aceca8 --- /dev/null +++ b/anbs_cpfn/Classes/NetTypeConverter.cs @@ -0,0 +1,35 @@ +using System.Text.Encodings.Web; + +using Microsoft.AspNetCore.Html; + +namespace anbs_cp.ForNet.Classes; + +/// +/// Расширение конвертера типов на манер Delphi +/// +public static class NetTypeConverter +{ + #region Конвернтация IHtmlContent + /// + /// Преобразует тип в строку . + /// + /// Значение, которое нужно преобразовать. + /// + public static string HtmlContentToString(IHtmlContent content) + { + //Создаём writer + using StringWriter writer = new(); + //Конвертируем IHtmlContent в string + content.WriteTo(writer, HtmlEncoder.Default); + //Возвращаем результат + return writer.ToString(); + } + + /// + /// Преобразует строку в тип . + /// + /// Значение, которое нужно преобразовать. + /// + public static IHtmlContent StringToHtmlContent(string content) => new HtmlContentBuilder().AppendHtml(content); + #endregion +} \ No newline at end of file diff --git a/anbs_cpfn/Classes/PasswordEncrypt.cs b/anbs_cpfn/Classes/PasswordEncrypt.cs new file mode 100644 index 0000000..a338eb2 --- /dev/null +++ b/anbs_cpfn/Classes/PasswordEncrypt.cs @@ -0,0 +1,56 @@ +using System.Text; + +using anbs_cp.Interfaces; + +using Microsoft.AspNetCore.Cryptography.KeyDerivation; + +namespace anbs_cp.ForNet.Classes; + +/// +/// Класс шифрования пароля +/// +public sealed class PasswordEncrypt: IEncryptor +{ + /// + /// Шифрование пароля + /// + /// Пароль + /// Хэш-код пароля + /// Зашифрованный пароль + public string Encrypt (string password, string salt) + { + // Получаю byte-массив из хэш-кода пароля + byte[] saltBytes = Encoding.UTF8.GetBytes(salt); + + // Шифрую пароль + byte[] encryptedPassword = KeyDerivation.Pbkdf2(password, saltBytes, KeyDerivationPrf.HMACSHA512, 5000, 64); + + // Возвращаю зашифрованный пароль + return Convert.ToBase64String(encryptedPassword); + } + + /// + /// Этот метод не требует реализации в этом классе! + /// + /// НЕ РАБОТАЕТ + /// НЕ РАБОТАЕТ + /// НЕ РАБОТАЕТ + /// Этот метод не требует реализации в этом классе! + public string Decrypt (string encryptedValue, string salt) => throw new NotImplementedException("Этот метод не требует реализации в этом классе!"); + + /// + /// Этот метод не требует реализации в этом классе! + /// + /// НЕ РАБОТАЕТ + /// НЕ РАБОТАЕТ + /// Этот метод не требует реализации в этом классе! + public string Base64UrlEncode (string text) => throw new NotImplementedException("Этот метод не требует реализации в этом классе!"); + + /// + /// Этот метод не требует реализации в этом классе! + /// + /// НЕ РАБОТАЕТ + /// НЕ РАБОТАЕТ + /// Этот метод не требует реализации в этом классе! + public string Base64UrlDecode (string text) => throw new NotImplementedException("Этот метод не требует реализации в этом классе!"); +} \ No newline at end of file diff --git a/anbs_cpfn/Extensions/UrlHelperExtension.cs b/anbs_cpfn/Extensions/UrlHelperExtension.cs new file mode 100644 index 0000000..a793f56 --- /dev/null +++ b/anbs_cpfn/Extensions/UrlHelperExtension.cs @@ -0,0 +1,110 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.WebUtilities; +using Microsoft.Extensions.Primitives; + +namespace anbs_cp.ForNet.Extensions; + +/// +/// Расширение URLHelper +/// +public static class UrlHelperExtension +{ + /// + /// Очищает URL, удаляя ненужные QueryString + /// + /// + /// + /// + /// + /// + /// + /// Ссылка, которую нужно почистить + /// Массив ключей, которые нужно удалить + /// Возвращать только локальную ссылку + /// + public static string ParseURLQuery(this IUrlHelper helper, HttpContext context, string? url, + string[] clearQueryString, bool getLocalURL = true) + { + //Получаю returnURL + url ??= "/"; + + //Если адрес локальный, то преобразую в полный + if (helper.IsLocalUrl(url)) + url = LocalToFullURL(helper, context, url); + + //Создаю uri по адресу + Uri uri = new(url ?? ""); + + //Формат + const UriFormat format = UriFormat.UriEscaped; + + //Формирую Uri-адрес сайта + string baseUri = + uri.GetComponents(UriComponents.Scheme | UriComponents.Host | UriComponents.Port, + format); + + //Формирую локальную ссылку + string localUri = uri.GetComponents(UriComponents.Path, format); + + //Создаю словарь запроса + Dictionary query = QueryHelpers.ParseQuery(uri.Query); + + //Если он содержит параметр для очистки, то удаляю его + foreach (KeyValuePair queryItem in query.Where(queryItem => + clearQueryString.Contains(queryItem.Key))) + query.Remove(queryItem.Key); + + //Создаю список запроса, пригодный для QueryBuilder + List> queryList = query.Select(static queryItem => + new KeyValuePair(queryItem.Key, queryItem.Value.ToString())).ToList(); + + //Запускаю построение новых параметров + QueryBuilder qBuilder = new(queryList); + + //Создаю переменную-результат + string result = ""; + + //Если нужно получить полную ссылку + if (!getLocalURL) + result = baseUri; + + //формирую переменную-результат + result = $"{result}/{localUri}{qBuilder.ToQueryString()}"; + + //Вывожу результат + return result; + } + + /// + /// Получает локальный url-адрес + /// + /// + /// url-адрес + /// Локальный url-адрес + public static string ToLocalURL (this IUrlHelper helper, string url) + { + //Создаю uri из url + Uri uri = new(url); + + //Вывожу результат + return helper.IsLocalUrl(url) ? url : uri.PathAndQuery; + } + + /// + /// Преобразует локальную ссылку в полную + /// + /// + /// + /// + /// + /// + /// + /// Ссылка + /// + /// + /// + public static string? LocalToFullURL (this IUrlHelper helper, HttpContext context, string? url) => + helper.IsLocalUrl(url) ? $"{context.Request.Scheme}://{context.Request.Host}{url}" : url; +} \ No newline at end of file diff --git a/anbs_cpfn/anbs_cpfn.csproj b/anbs_cpfn/anbs_cpfn.csproj new file mode 100644 index 0000000..dda3682 --- /dev/null +++ b/anbs_cpfn/anbs_cpfn.csproj @@ -0,0 +1,38 @@ + + + + net8.0 + enable + enable + True + ANBSoftware.ComponentsPackForNet + 2023.11.14.0 + Александр Бабаев + Набор компонентов ANB Software для ASP.NET Core + Библиотека полезных методов языка C# для ASP.NET Core + Александр Бабаев + https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack + https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack + git + MIT + anbs_cp.ForNet + anbs_cp_fn + + + + + + + + + + + + + + + + + + + diff --git a/anbs_cpfn/anbs_cpfn.csproj.DotSettings b/anbs_cpfn/anbs_cpfn.csproj.DotSettings new file mode 100644 index 0000000..632c268 --- /dev/null +++ b/anbs_cpfn/anbs_cpfn.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp120 \ No newline at end of file diff --git a/anbs_cposinfo/Classes/OsDriveInfo.cs b/anbs_cposinfo/Classes/OsDriveInfo.cs new file mode 100644 index 0000000..8ec8ce0 --- /dev/null +++ b/anbs_cposinfo/Classes/OsDriveInfo.cs @@ -0,0 +1,59 @@ +using anbs_cp.OsInfo.Enums; +using anbs_cp.OsInfo.Interfaces; + +namespace anbs_cp.OsInfo.Classes; + +/// +/// Информация о дисках +/// +public sealed class OsDriveInfo: IOsDriveInfo +{ + /// + /// Конструктор + /// + public OsDriveInfo () + { + Type = EDriveType.DtHardDisc; + Caption = null; + Description = null; + DeviceId = null; + Name = null; + Model = null; + TotalSize = 0; + } + + /// + /// Тип диска + /// + public EDriveType Type { get; set; } + + /// + /// Заголовок + /// + public string? Caption { get; set; } + + /// + /// Описание + /// + public string? Description { get; set; } + + /// + /// Идентификатор устройства + /// + public string? DeviceId { get; set; } + + /// + /// Имя устройства + /// + public string? Name { get; set; } + + /// + /// Модель + /// + public string? Model { get; set; } + + /// + /// Общий размер + /// + public ulong TotalSize { get; set; } +} \ No newline at end of file diff --git a/anbs_cposinfo/Classes/OsInfo.cs b/anbs_cposinfo/Classes/OsInfo.cs new file mode 100644 index 0000000..7b6da2d --- /dev/null +++ b/anbs_cposinfo/Classes/OsInfo.cs @@ -0,0 +1,402 @@ +using System.Management; +using System.Net.NetworkInformation; +using System.Net.Sockets; + +using anbs_cp.Classes; +using anbs_cp.OsInfo.Enums; +using anbs_cp.OsInfo.Interfaces; + +namespace anbs_cp.OsInfo.Classes; + +/// +/// Информация о системе +/// +public static class OsInfo +{ + /// + /// Конструктор + /// + static OsInfo () + { + Windows = GetWindowsInfo(); + Processors = GetProcessors(); + RAM = GetRAMs(); + Videos = GetVideoAdapterInfos(); + Drives = GetDriveInfos(); + Net = GetNet(); + } + + /// + /// Информация о Windows + /// + public static IOsWindowsInfo Windows { get; } + + /// + /// Список с информацией о процессоре(-ах) + /// + public static List Processors { get; } + + /// + /// Количество оперативной памяти в байтах + /// + public static ulong RAM { get; } + + /// + /// Видеоадаптеры + /// + public static List Videos { get; } + + /// + /// Диски + /// + public static List Drives { get; set; } + + /// + /// Сеть + /// + public static List Net { get; set; } + + #region Служебные методы + /// + /// Получает информацию о Windows + /// + /// + private static IOsWindowsInfo GetWindowsInfo () => + new OsWindowsInfo + { + Version = Environment.OSVersion.ToString(), + Is64 = Environment.Is64BitOperatingSystem, + PcName = Environment.MachineName, + WindowsFolder = Environment.SystemDirectory + }; + + /// + /// Получение процессоров + /// + /// Список информации о процессорах + private static List GetProcessors () + { + try + { + //Создаю результирующий список + List processorsList = new(); + + //Создаю классы менеджмента + ManagementClass management = new("Win32_Processor"); + ManagementObjectCollection collection = management.GetInstances(); + + //Получаю число процессоров + int processorsCount = collection.Cast() + .Select(static a => a.Properties["ProcessorId"].Value.ToString()).Count(); + + //Перебираю массив данных + for (int ind = 0; ind < processorsCount; ind++) + { + //Создаю элемент информации о процессоре + OsProcessorInfo processor = new() + { + Caption = collection.Cast() + .Select(static a => a.Properties["Caption"].Value.ToString()).ElementAtOrDefault(ind), + Description = collection.Cast() + .Select(static a => a.Properties["Description"].Value.ToString()).ElementAtOrDefault(ind), + DeviceId = collection.Cast() + .Select(static a => a.Properties["DeviceID"].Value.ToString()).ElementAtOrDefault(ind), + Manufacturer = collection.Cast() + .Select(static a => a.Properties["Manufacturer"].Value.ToString()).ElementAtOrDefault(ind), + MaxClockSpeed = TypeConverter.StrToInt(collection.Cast() + .Select(static a => + a.Properties["MaxClockSpeed"].Value.ToString()) + .ElementAtOrDefault(ind) ?? + "0"), + Name = collection.Cast() + .Select(static a => a.Properties["Name"].Value.ToString()).ElementAtOrDefault(ind), + NumberOfCores = TypeConverter.StrToInt(collection.Cast() + .Select(static a => + a.Properties["NumberOfCores"].Value.ToString()) + .ElementAtOrDefault(ind) ?? + "0"), + NumberOfLogicalProcessors = TypeConverter.StrToInt(collection.Cast() + .Select(static a => a.Properties["NumberOfLogicalProcessors"].Value.ToString()) + .ElementAtOrDefault(ind) ?? "0") + }; + + //Добавляю в список + processorsList.Add(processor); + } + + //Возвращаю список + return processorsList; + } + catch (NullReferenceException) + { + return new(); + } + } + + /// + /// Получение общее количество оперативной памяти + /// + /// Список информации о количестве оперативной памяти + private static ulong GetRAMs () + { + try + { + //Создаю классы менеджмента + ManagementClass management = new("Win32_ComputerSystem"); + ManagementObjectCollection collection = management.GetInstances(); + + //Получаю результат + return TypeConverter.StrToUInt64(collection.Cast() + .Select(static a => a.Properties["TotalPhysicalMemory"].Value.ToString()).FirstOrDefault() ?? "0"); + } + catch (NullReferenceException) + { + return 0; + } + } + + /// + /// Получает список видеоадаптеров + /// + /// Список информации о видеоадаптерах + private static List GetVideoAdapterInfos () + { + try + { + //Создаю результирующий список + List videosList = new(); + + //Создаю классы менеджмента + ManagementClass management = new("Win32_VideoController"); + ManagementObjectCollection collection = management.GetInstances(); + + //Получаю число адаптеров + int count = collection.Cast() + .Select(static a => a.Properties["DeviceID"].Value.ToString()).Count(); + + //Перебираю массив данных + for (int ind = 0; ind < count; ind++) + { + //Создаю элемент информации об адаптере + OsVideoAdapterInfo adapter = new() + { + Caption = collection.Cast() + .Select(static a => a.Properties["Caption"].Value.ToString()).ElementAtOrDefault(ind), + Description = collection.Cast() + .Select(static a => a.Properties["Description"].Value.ToString()).ElementAtOrDefault(ind), + DeviceId = collection.Cast() + .Select(static a => a.Properties["DeviceID"].Value.ToString()).ElementAtOrDefault(ind), + AdapterRAM = TypeConverter.StrToInt(collection.Cast() + .Select(static a => a.Properties["AdapterRAM"].Value.ToString()).ElementAtOrDefault(ind) ?? "0"), + DriverDate = collection.Cast() + .Select(static a => a.Properties["DriverDate"].Value.ToString()).ElementAtOrDefault(ind), + Name = collection.Cast() + .Select(static a => a.Properties["Name"].Value.ToString()).ElementAtOrDefault(ind), + CurrentResolution = (TypeConverter.StrToInt(collection.Cast() + .Select(static a => a.Properties["CurrentHorizontalResolution"].Value.ToString()).ElementAtOrDefault(ind) ?? "0"), + TypeConverter.StrToInt(collection.Cast() + .Select(static a => a.Properties["CurrentVerticalResolution"].Value.ToString()) + .ElementAtOrDefault(ind) ?? "0")), + SystemName = collection.Cast() + .Select(static a => a.Properties["SystemName"].Value.ToString()).ElementAtOrDefault(ind), + DriverVersion = collection.Cast() + .Select(static a => a.Properties["DriverVersion"].Value.ToString()).ElementAtOrDefault(ind), + InstalledDisplayDrivers = collection.Cast() + .Select(static a => a.Properties["InstalledDisplayDrivers"].Value.ToString()).ElementAtOrDefault(ind), + VideoProcessor = collection.Cast() + .Select(static a => a.Properties["VideoProcessor"].Value.ToString()).ElementAtOrDefault(ind) + }; + + //Добавляю в список + videosList.Add(adapter); + } + + //Возвращаю список + return videosList; + } + catch (NullReferenceException) + { + return new(); + } + } + + /// + /// Получает список дисков + /// + /// Список информации о дисках + private static List GetDriveInfos () + { + try + { + //Создаю результат + List result = new(); + + //Добавление всех HDD/SSD дисков + result.AddRange(GetHDDs()); + + //Добавление всех CD/DVD/BD дисков + result.AddRange(GetCDRom()); + + //Вывожу список + return result; + } + catch (NullReferenceException) + { + return new(); + } + } + + /// + /// Получаю список HDD/SSD дисков + /// + /// Информация обо всех HDD/SSD дисках + private static List GetHDDs () + { + try + { + //Создаю результирующий список + List driveList = new(); + + //Создаю классы менеджмента + ManagementClass management = new("Win32_DiskDrive"); + ManagementObjectCollection collection = management.GetInstances(); + + //Получаю число адаптеров + int count = collection.Cast() + .Select(static a => a.Properties["DeviceID"].Value.ToString()).Count(); + + //Перебираю массив данных + for (int ind = 0; ind < count; ind++) + { + //Создаю элемент информации об адаптере + OsDriveInfo drive = new() + { + Type = EDriveType.DtHardDisc, + Caption = collection.Cast() + .Select(static a => a.Properties["Caption"].Value.ToString()).ElementAtOrDefault(ind), + Description = collection.Cast() + .Select(static a => a.Properties["Description"].Value.ToString()).ElementAtOrDefault(ind), + DeviceId = collection.Cast() + .Select(static a => a.Properties["DeviceID"].Value.ToString()).ElementAtOrDefault(ind), + Name = collection.Cast() + .Select(static a => a.Properties["Name"].Value.ToString()).ElementAtOrDefault(ind), + TotalSize = TypeConverter.StrToUInt64(collection.Cast() + .Select(static a => a.Properties["Size"].Value.ToString()).ElementAtOrDefault(ind) ?? "0"), + Model = collection.Cast() + .Select(static a => a.Properties["Model"].Value.ToString()).ElementAtOrDefault(ind) + }; + + //Добавляю в список + driveList.Add(drive); + } + + //Возвращаю список + return driveList; + } + catch (NullReferenceException) + { + return new(); + } + } + + /// + /// Получаю список CD/DVD/BD дисков + /// + /// Информация обо всех CD/DVD/BD дисках + private static List GetCDRom () + { + try + { + //Создаю результирующий список + List driveList = new(); + + //Создаю классы менеджмента + ManagementClass management = new("Win32_CDROMDrive"); + ManagementObjectCollection collection = management.GetInstances(); + + //Получаю число адаптеров + int count = collection.Cast() + .Select(static a => a.Properties["DeviceID"].Value.ToString()).Count(); + + //Перебираю массив данных + for (int ind = 0; ind < count; ind++) + { + //Создаю элемент информации об адаптере + OsDriveInfo drive = new() + { + Type = EDriveType.DtCDRom, + Caption = collection.Cast() + .Select(static a => a.Properties["Caption"].Value.ToString()).ElementAtOrDefault(ind), + Description = collection.Cast() + .Select(static a => a.Properties["Description"].Value.ToString()).ElementAtOrDefault(ind), + DeviceId = collection.Cast() + .Select(static a => a.Properties["DeviceID"].Value.ToString()).ElementAtOrDefault(ind), + Name = collection.Cast() + .Select(static a => a.Properties["Name"].Value.ToString()).ElementAtOrDefault(ind), + //Ставится 0, чтобы не проверять корректность загрузки и читаемость диска, а также избежать удлинения получения информации + TotalSize = 0, + Model = collection.Cast() + .Select(static a => a.Properties["Manufacturer"].Value.ToString()).ElementAtOrDefault(ind) + }; + + //Добавляю в список + driveList.Add(drive); + } + + //Возвращаю список + return driveList; + } + catch (NullReferenceException) + { + return new(); + } + } + + /// + /// Получаю информацию о сети интернет + /// + /// Информация о сети интернет + private static List GetNet () + { + try + { + //Создаю результирующий список + List netList = new(); + + //Получаю информацию о всех сетевых интерфейсах + foreach (NetworkInterface adapter in NetworkInterface.GetAllNetworkInterfaces()) + { + //Создаю элемент + OsNetInfo netInfo = new() + { + Name = adapter.Name, + Description = adapter.Description, + MacAddress = adapter.OperationalStatus == OperationalStatus.Up + ? adapter.GetPhysicalAddress().ToString() + : null + }; + + //Получаю IP-адрес + foreach (UnicastIPAddressInformation info in adapter.GetIPProperties().UnicastAddresses.Where( + static info => + info.Address.AddressFamily == AddressFamily.InterNetwork && info.IsDnsEligible)) + { + if (!string.IsNullOrWhiteSpace(netInfo.IPAddress)) + netInfo.IPAddress += ";"; + netInfo.IPAddress += info.Address.ToString(); + } + + //Добавляю адаптер + netList.Add(netInfo); + } + + //Возвращаю список + return netList; + } + catch (NullReferenceException) + { + return new(); + } + } + #endregion +} \ No newline at end of file diff --git a/anbs_cposinfo/Classes/OsNetInfo.cs b/anbs_cposinfo/Classes/OsNetInfo.cs new file mode 100644 index 0000000..e5b416b --- /dev/null +++ b/anbs_cposinfo/Classes/OsNetInfo.cs @@ -0,0 +1,39 @@ +using anbs_cp.OsInfo.Interfaces; + +namespace anbs_cp.OsInfo.Classes; + +/// +/// Информация об интернет-соединении +/// +public sealed class OsNetInfo: IOsNetInfo +{ + /// + /// Заголовок + /// + public string? Caption { get => Name; set => _ = value; } + + /// + /// Описание + /// + public string? Description { get; set; } + + /// + /// Идентификатор устройства + /// + public string? DeviceId { get => Name; set => _ = value; } + + /// + /// Имя устройства + /// + public string? Name { get; set; } + + /// + /// IP-адрес + /// + public string? IPAddress { get; set; } + + /// + /// MAC-адрес + /// + public string? MacAddress { get; set; } +} \ No newline at end of file diff --git a/anbs_cposinfo/Classes/OsProcessorInfo.cs b/anbs_cposinfo/Classes/OsProcessorInfo.cs new file mode 100644 index 0000000..df3bba8 --- /dev/null +++ b/anbs_cposinfo/Classes/OsProcessorInfo.cs @@ -0,0 +1,64 @@ +using anbs_cp.OsInfo.Interfaces; + +namespace anbs_cp.OsInfo.Classes; + +/// +/// Класс информации о процессоре +/// +public sealed class OsProcessorInfo: IOsProcessorInfo +{ + /// + /// Конструктор + /// + public OsProcessorInfo () + { + Caption = null; + Description = null; + DeviceId = null; + Manufacturer = null; + MaxClockSpeed = 0; + Name = null; + NumberOfCores = 0; + NumberOfLogicalProcessors = 0; + } + + /// + /// Заголовок + /// + public string? Caption { get; set; } + + /// + /// Описание + /// + public string? Description { get; set; } + + /// + /// Идентификатор процессора в системе + /// + public string? DeviceId { get; set; } + + /// + /// Производитель + /// + public string? Manufacturer { get; set; } + + /// + /// Максимальная тактовая частота + /// + public int MaxClockSpeed { get; set; } + + /// + /// Имя процессора + /// + public string? Name { get; set; } + + /// + /// Число ядер + /// + public int NumberOfCores { get; set; } + + /// + /// Число потоков + /// + public int NumberOfLogicalProcessors { get; set; } +} \ No newline at end of file diff --git a/anbs_cposinfo/Classes/OsVideoAdapterInfo.cs b/anbs_cposinfo/Classes/OsVideoAdapterInfo.cs new file mode 100644 index 0000000..2b46a7a --- /dev/null +++ b/anbs_cposinfo/Classes/OsVideoAdapterInfo.cs @@ -0,0 +1,82 @@ +using anbs_cp.OsInfo.Interfaces; + +namespace anbs_cp.OsInfo.Classes; + +/// +/// Информация о видеокарте +/// +internal sealed class OsVideoAdapterInfo: IOsVideoAdapterInfo +{ + /// + /// Конструктор + /// + public OsVideoAdapterInfo () + { + AdapterRAM = 0; + Caption = null; + CurrentResolution = (0, 0); + Description = null; + DeviceId = null; + DriverDate = null; + DriverVersion = null; + InstalledDisplayDrivers = null; + Name = null; + SystemName = null; + VideoProcessor = null; + } + + /// + /// Память + /// + public int AdapterRAM { get; set; } + + /// + /// Заголовок + /// + public string? Caption { get; set; } + + /// + /// Текущее разрешение + /// + public (int, int) CurrentResolution { get; set; } + + /// + /// Описание + /// + public string? Description { get; set; } + + /// + /// Идентификатор устройства + /// + public string? DeviceId { get; set; } + + /// + /// Дата установки драйвера + /// + public string? DriverDate { get; set; } + + /// + /// Версия драйвера + /// + public string? DriverVersion { get; set; } + + /// + /// Название драйверов + /// + public string? InstalledDisplayDrivers { get; set; } + + /// + /// Имя + /// + public string? Name { get; set; } + + /// + /// Имя в системе + /// + public string? SystemName { get; set; } + + /// + /// Видео процессор + /// + public string? VideoProcessor { get; set; } +} \ No newline at end of file diff --git a/anbs_cposinfo/Classes/OsWindowsInfo.cs b/anbs_cposinfo/Classes/OsWindowsInfo.cs new file mode 100644 index 0000000..3218361 --- /dev/null +++ b/anbs_cposinfo/Classes/OsWindowsInfo.cs @@ -0,0 +1,62 @@ +using anbs_cp.OsInfo.Interfaces; + +namespace anbs_cp.OsInfo.Classes; + +/// +/// Информация о Windows +/// +public sealed class OsWindowsInfo: IOsWindowsInfo +{ + /// + /// Конструктор + /// + public OsWindowsInfo () + { + Version = null; + Is64 = true; + PcName = null; + WindowsFolder = null; + } + + /// + /// Версия + /// + public string? Version { get; set; } + + /// + /// 64-разрядная ОС + /// + public bool Is64 { get; set; } + + /// + /// Имя компьютера + /// + public string? PcName { get; set; } + + /// + /// Путь к папке Windows + /// + public string? WindowsFolder { get; set; } + + #region Реализация интерфейса IBasicInfo + /// + /// Заголовок + /// + public string? Caption { get => Version; set => _ = value; } + + /// + /// Описание + /// + public string? Description { get => Version; set => _ = value; } + + /// + /// Идентификатор + /// + public string? DeviceId { get => Version; set => _ = value; } + + /// + /// Имя + /// + public string? Name { get => Version; set => _ = value; } + #endregion +} \ No newline at end of file diff --git a/anbs_cposinfo/Enums/EDriveType.cs b/anbs_cposinfo/Enums/EDriveType.cs new file mode 100644 index 0000000..c8af779 --- /dev/null +++ b/anbs_cposinfo/Enums/EDriveType.cs @@ -0,0 +1,17 @@ +namespace anbs_cp.OsInfo.Enums; + +/// +/// Тип носителя +/// +public enum EDriveType +{ + /// + /// HDD/SSD/M2 + /// + DtHardDisc = 0, + + /// + /// Диск CD/DVD/BD + /// + DtCDRom = 1 +} \ No newline at end of file diff --git a/anbs_cposinfo/Interfaces/IOsBasicInfo.cs b/anbs_cposinfo/Interfaces/IOsBasicInfo.cs new file mode 100644 index 0000000..2d40df6 --- /dev/null +++ b/anbs_cposinfo/Interfaces/IOsBasicInfo.cs @@ -0,0 +1,27 @@ +namespace anbs_cp.OsInfo.Interfaces; + +/// +/// Базовые параметры устройства +/// +public interface IOsBasicInfo +{ + /// + /// Заголовок + /// + public string? Caption { get; set; } + + /// + /// Описание + /// + public string? Description { get; set; } + + /// + /// Идентификатор устройства + /// + public string? DeviceId { get; set; } + + /// + /// Имя устройства + /// + public string? Name { get; set; } +} \ No newline at end of file diff --git a/anbs_cposinfo/Interfaces/IOsDriveInfo.cs b/anbs_cposinfo/Interfaces/IOsDriveInfo.cs new file mode 100644 index 0000000..04cfdd1 --- /dev/null +++ b/anbs_cposinfo/Interfaces/IOsDriveInfo.cs @@ -0,0 +1,24 @@ +using anbs_cp.OsInfo.Enums; + +namespace anbs_cp.OsInfo.Interfaces; + +/// +/// Информация о дисках +/// +public interface IOsDriveInfo: IOsBasicInfo +{ + /// + /// Тип диска + /// + public EDriveType Type { get; set; } + + /// + /// Модель + /// + public string? Model { get; set; } + + /// + /// Общий размер + /// + public ulong TotalSize { get; set; } +} \ No newline at end of file diff --git a/anbs_cposinfo/Interfaces/IOsNetInfo.cs b/anbs_cposinfo/Interfaces/IOsNetInfo.cs new file mode 100644 index 0000000..5e54e62 --- /dev/null +++ b/anbs_cposinfo/Interfaces/IOsNetInfo.cs @@ -0,0 +1,17 @@ +namespace anbs_cp.OsInfo.Interfaces; + +/// +/// Информация об интернет-соединении +/// +public interface IOsNetInfo: IOsBasicInfo +{ + /// + /// IP-адрес + /// + public string? IPAddress { get; set; } + + /// + /// MAC-адрес + /// + public string? MacAddress { get; set; } +} \ No newline at end of file diff --git a/anbs_cposinfo/Interfaces/IOsProcessorInfo.cs b/anbs_cposinfo/Interfaces/IOsProcessorInfo.cs new file mode 100644 index 0000000..56b8179 --- /dev/null +++ b/anbs_cposinfo/Interfaces/IOsProcessorInfo.cs @@ -0,0 +1,31 @@ +namespace anbs_cp.OsInfo.Interfaces; + +/// +/// Информация о процессоре +/// +public interface IOsProcessorInfo: IOsBasicInfo +{ + /// + /// Заголовок + /// + + /// + /// Производитель + /// + public string? Manufacturer { get; set; } + + /// + /// Максимальная тактовая частота + /// + public int MaxClockSpeed { get; set; } + + /// + /// Число ядер + /// + public int NumberOfCores { get; set; } + + /// + /// Число потоков + /// + public int NumberOfLogicalProcessors { get; set; } +} \ No newline at end of file diff --git a/anbs_cposinfo/Interfaces/IOsVideoAdapterInfo.cs b/anbs_cposinfo/Interfaces/IOsVideoAdapterInfo.cs new file mode 100644 index 0000000..9b4c6a2 --- /dev/null +++ b/anbs_cposinfo/Interfaces/IOsVideoAdapterInfo.cs @@ -0,0 +1,42 @@ +namespace anbs_cp.OsInfo.Interfaces; + +/// +/// Информация о видеокарте +/// +public interface IOsVideoAdapterInfo: IOsBasicInfo +{ + /// + /// Память + /// + public int AdapterRAM { get; set; } + + /// + /// Текущее разрешение + /// + public (int, int) CurrentResolution { get; set; } + + /// + /// Дата установки драйвера + /// + public string? DriverDate { get; set; } + + /// + /// Версия драйвера + /// + public string? DriverVersion { get; set; } + + /// + /// Название драйверов + /// + public string? InstalledDisplayDrivers { get; set; } + + /// + /// Имя в системе + /// + public string? SystemName { get; set; } + + /// + /// Видео процессор + /// + public string? VideoProcessor { get; set; } +} \ No newline at end of file diff --git a/anbs_cposinfo/Interfaces/IOsWindowsInfo.cs b/anbs_cposinfo/Interfaces/IOsWindowsInfo.cs new file mode 100644 index 0000000..7459f82 --- /dev/null +++ b/anbs_cposinfo/Interfaces/IOsWindowsInfo.cs @@ -0,0 +1,27 @@ +namespace anbs_cp.OsInfo.Interfaces; + +/// +/// Информация о Windows +/// +public interface IOsWindowsInfo: IOsBasicInfo +{ + /// + /// Версия + /// + public string? Version { get; set; } + + /// + /// 64-разрядная ОС + /// + public bool Is64 { get; set; } + + /// + /// Имя компьютера + /// + public string? PcName { get; set; } + + /// + /// Путь к папке Windows + /// + public string? WindowsFolder { get; set; } +} \ No newline at end of file diff --git a/anbs_cposinfo/anbs_cposinfo.csproj b/anbs_cposinfo/anbs_cposinfo.csproj new file mode 100644 index 0000000..45b2409 --- /dev/null +++ b/anbs_cposinfo/anbs_cposinfo.csproj @@ -0,0 +1,28 @@ + + + + net8.0 + enable + enable + anbs_cp.OsInfo + True + ANBSoftware.ComponentsPackOsInfo + 2023.11.14 + Александр Бабаев + Набор компонентов ANB Software для получения информации о Windows + Библиотека полезных методов языка C# для получения информации об Windows + Александр Бабаев + https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack + https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack + git + + + + + + + + + + + diff --git a/anbs_cposinfo/anbs_cposinfo.csproj.DotSettings b/anbs_cposinfo/anbs_cposinfo.csproj.DotSettings new file mode 100644 index 0000000..632c268 --- /dev/null +++ b/anbs_cposinfo/anbs_cposinfo.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp120 \ No newline at end of file diff --git a/anbsoftware.componentspack.sln b/anbsoftware.componentspack.sln index adc732b..0760bba 100644 --- a/anbsoftware.componentspack.sln +++ b/anbsoftware.componentspack.sln @@ -5,11 +5,17 @@ VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cp", "anbs_cp\anbs_cp.csproj", "{442A56CC-1061-4EB5-8B67-3E3D997976D7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "demo", "demo\demo.csproj", "{3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "demo", "demo\demo.csproj", "{3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}" ProjectSection(ProjectDependencies) = postProject {442A56CC-1061-4EB5-8B67-3E3D997976D7} = {442A56CC-1061-4EB5-8B67-3E3D997976D7} EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cpfn", "anbs_cpfn\anbs_cpfn.csproj", "{EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cposinfo", "anbs_cposinfo\anbs_cposinfo.csproj", "{80E1FEA9-EEDA-4411-8EBA-11991432E98E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cpdb", "anbs_cpdb\anbs_cpdb.csproj", "{3796862F-F181-4A27-92D8-8BF13C4FD711}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -23,6 +29,18 @@ Global {3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}.Debug|Any CPU.ActiveCfg = Release|Any CPU {3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}.Debug|Any CPU.Build.0 = Release|Any CPU {3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}.Release|Any CPU.ActiveCfg = Debug.CNF|Any CPU + {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Release|Any CPU.Build.0 = Release|Any CPU + {80E1FEA9-EEDA-4411-8EBA-11991432E98E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80E1FEA9-EEDA-4411-8EBA-11991432E98E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80E1FEA9-EEDA-4411-8EBA-11991432E98E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80E1FEA9-EEDA-4411-8EBA-11991432E98E}.Release|Any CPU.Build.0 = Release|Any CPU + {3796862F-F181-4A27-92D8-8BF13C4FD711}.Debug|Any CPU.ActiveCfg = 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.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/anbsoftware.componentspack.sln.DotSettings b/anbsoftware.componentspack.sln.DotSettings new file mode 100644 index 0000000..94e58b5 --- /dev/null +++ b/anbsoftware.componentspack.sln.DotSettings @@ -0,0 +1,30 @@ + + CD + HD + HDD + RA + RAM + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True \ No newline at end of file diff --git a/demo/CountValueTest.Designer.cs b/demo/CountValueTest.Designer.cs index 6656a3b..2088b44 100644 --- a/demo/CountValueTest.Designer.cs +++ b/demo/CountValueTest.Designer.cs @@ -1,39 +1,40 @@ -namespace demo +namespace demo; + +sealed partial class CountValueTest { - partial class CountValueTest + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) + if (disposing && (components != null)) { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); + components.Dispose(); } + base.Dispose(disposing); + } - #region Windows Form Designer generated code + #region Windows Form Designer generated code - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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 @@ -41,16 +42,17 @@ this.InsertDataLabel.AutoSize = true; this.InsertDataLabel.Location = new System.Drawing.Point(12, 66); this.InsertDataLabel.Name = "InsertDataLabel"; - this.InsertDataLabel.Size = new System.Drawing.Size(197, 17); + this.InsertDataLabel.Size = new System.Drawing.Size(341, 17); this.InsertDataLabel.TabIndex = 0; - this.InsertDataLabel.Text = "&Insert any int value:"; + this.InsertDataLabel.Text = "&Введите любое целочисленное значение:"; // // InsertDataBox // this.InsertDataBox.Location = new System.Drawing.Point(12, 86); this.InsertDataBox.Name = "InsertDataBox"; - this.InsertDataBox.Size = new System.Drawing.Size(246, 24); + this.InsertDataBox.Size = new System.Drawing.Size(457, 24); this.InsertDataBox.TabIndex = 1; + this.InsertDataBox.TextChanged += new System.EventHandler(this.InsertDataBox_TextChanged); // // ResultLabel // @@ -59,19 +61,19 @@ 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(270, 79); + this.ResultLabel.Size = new System.Drawing.Size(478, 79); this.ResultLabel.TabIndex = 2; - this.ResultLabel.Text = "&Insert any int value to insert box above and press \"Calculate\" button to see res" + - "ult..."; + this.ResultLabel.Text = "&Вставьте любое целочисленное значение в поле выше и нажмите кнопку \"Вычислить\", " + + "чтобы увидеть результат..."; this.ResultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // CalculateButton // - this.CalculateButton.Location = new System.Drawing.Point(81, 116); + this.CalculateButton.Location = new System.Drawing.Point(12, 116); this.CalculateButton.Name = "CalculateButton"; - this.CalculateButton.Size = new System.Drawing.Size(103, 23); + this.CalculateButton.Size = new System.Drawing.Size(234, 23); this.CalculateButton.TabIndex = 3; - this.CalculateButton.Text = "Calc&ulate"; + this.CalculateButton.Text = "В&ычислить обработчиком"; this.CalculateButton.UseVisualStyleBackColor = true; this.CalculateButton.Click += new System.EventHandler(this.CalculateButton_Click); // @@ -80,9 +82,9 @@ this.SelectFormatterLabel.AutoSize = true; this.SelectFormatterLabel.Location = new System.Drawing.Point(12, 9); this.SelectFormatterLabel.Name = "SelectFormatterLabel"; - this.SelectFormatterLabel.Size = new System.Drawing.Size(161, 17); + this.SelectFormatterLabel.Size = new System.Drawing.Size(188, 17); this.SelectFormatterLabel.TabIndex = 4; - this.SelectFormatterLabel.Text = "&Select formatter:"; + this.SelectFormatterLabel.Text = "В&ыберете обработчик:"; // // SelectFormatterBox // @@ -90,18 +92,29 @@ this.SelectFormatterBox.FlatStyle = System.Windows.Forms.FlatStyle.System; this.SelectFormatterBox.FormattingEnabled = true; this.SelectFormatterBox.Items.AddRange(new object[] { - "CountFormatter", - "FileSizeFormatter"}); + "Обработчик счёта", + "Обработчик размера файла"}); this.SelectFormatterBox.Location = new System.Drawing.Point(12, 29); this.SelectFormatterBox.Name = "SelectFormatterBox"; - this.SelectFormatterBox.Size = new System.Drawing.Size(246, 25); + 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(270, 222); + 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); @@ -115,20 +128,20 @@ this.Name = "CountValueTest"; this.ShowIcon = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Formatter Test Unit"; + 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; } + + #endregion + + private Label InsertDataLabel; + private TextBox InsertDataBox; + private Label ResultLabel; + private Button CalculateButton; + private Label SelectFormatterLabel; + private ComboBox SelectFormatterBox; + private Button calculateConvButton; } \ No newline at end of file diff --git a/demo/CountValueTest.cs b/demo/CountValueTest.cs index defe9b7..4afcb46 100644 --- a/demo/CountValueTest.cs +++ b/demo/CountValueTest.cs @@ -1,42 +1,56 @@ -using anbs_cp; -namespace demo +using anbs_cp.Classes; +using anbs_cp.Interfaces; + +namespace demo; + +public sealed partial class CountValueTest: Form { - public partial class CountValueTest : Form + public CountValueTest () { - 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 { - InitializeComponent(); - } + 0 => new CountFormatter(), + 1 => new FileSizeFormatter(), + _ => new CountFormatter(), + }; + ResultLabel.Text = formatter.Format(value); + } - private void CalculateButton_Click(object sender, EventArgs e) + 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 { - - if (string.IsNullOrEmpty(InsertDataBox.Text)) - return; - - IValueFormatter formatter; - - long value = TypeConverter.StrToInt64(InsertDataBox.Text); - - switch (SelectFormatterBox.SelectedIndex) - { - case 0: - formatter = new CountFormatter(); - break; - case 1: - formatter = new FileSizeFormatter(); - break; - default: - formatter = new CountFormatter(); - break; - } - - ResultLabel.Text = formatter.Format(value); - } - - private void CountValueTest_Load(object sender, EventArgs e) - { - SelectFormatterBox.SelectedIndex = 0; - } + 0 => new CountConverter(CountConverter.DefaultNames).Convert(value), + 1 => new FileSizeConverter(FileSizeConverter.DefaultNames).Convert(value), + _ => new CountConverter(CountConverter.DefaultNames).Convert(value) + }; } } \ No newline at end of file diff --git a/demo/FileHashAndMimeTypeTest.Designer.cs b/demo/FileHashAndMimeTypeTest.Designer.cs new file mode 100644 index 0000000..bb6e4f9 --- /dev/null +++ b/demo/FileHashAndMimeTypeTest.Designer.cs @@ -0,0 +1,125 @@ +namespace demo; + +sealed partial class FileHashAndMimeType +{ + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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; +} \ No newline at end of file diff --git a/demo/FileHashAndMimeTypeTest.cs b/demo/FileHashAndMimeTypeTest.cs new file mode 100644 index 0000000..69f7cf4 --- /dev/null +++ b/demo/FileHashAndMimeTypeTest.cs @@ -0,0 +1,42 @@ +using anbs_cp.Classes; +// ReSharper disable LocalizableElement + +namespace demo; + +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(); + } +} \ No newline at end of file diff --git a/demo/FileHashAndMimeTypeTest.resx b/demo/FileHashAndMimeTypeTest.resx new file mode 100644 index 0000000..e6275bd --- /dev/null +++ b/demo/FileHashAndMimeTypeTest.resx @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/demo/MainMenu.Designer.cs b/demo/MainMenu.Designer.cs new file mode 100644 index 0000000..a13600a --- /dev/null +++ b/demo/MainMenu.Designer.cs @@ -0,0 +1,102 @@ +namespace demo; + +sealed partial class MainMenu +{ + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent () + { + this.CountValueTest = new System.Windows.Forms.Button(); + this.SimpleMapperTest = new System.Windows.Forms.Button(); + this.FileExtensionTest = new System.Windows.Forms.Button(); + this.OsInfoBtn = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // CountValueTest + // + this.CountValueTest.Location = new System.Drawing.Point(12, 12); + this.CountValueTest.Name = "CountValueTest"; + this.CountValueTest.Size = new System.Drawing.Size(337, 53); + this.CountValueTest.TabIndex = 0; + this.CountValueTest.Text = "Новый тест модуля форматирования строки"; + this.CountValueTest.UseVisualStyleBackColor = true; + this.CountValueTest.Click += new System.EventHandler(this.button1_Click); + // + // SimpleMapperTest + // + this.SimpleMapperTest.Location = new System.Drawing.Point(12, 71); + this.SimpleMapperTest.Name = "SimpleMapperTest"; + this.SimpleMapperTest.Size = new System.Drawing.Size(335, 51); + this.SimpleMapperTest.TabIndex = 1; + this.SimpleMapperTest.Text = "Новый тест модуля SimpleMapper"; + this.SimpleMapperTest.UseVisualStyleBackColor = true; + this.SimpleMapperTest.Click += new System.EventHandler(this.SimpleMapperTest_Click); + // + // FileExtensionTest + // + this.FileExtensionTest.Location = new System.Drawing.Point(12, 128); + this.FileExtensionTest.Name = "FileExtensionTest"; + this.FileExtensionTest.Size = new System.Drawing.Size(335, 51); + this.FileExtensionTest.TabIndex = 2; + this.FileExtensionTest.Text = "Новый тест модуля FileExtension"; + this.FileExtensionTest.UseVisualStyleBackColor = true; + this.FileExtensionTest.Click += new System.EventHandler(this.FileExtensionTest_Click); + // + // OsInfoBtn + // + this.OsInfoBtn.Location = new System.Drawing.Point(12, 185); + this.OsInfoBtn.Name = "OsInfoBtn"; + this.OsInfoBtn.Size = new System.Drawing.Size(335, 51); + this.OsInfoBtn.TabIndex = 3; + this.OsInfoBtn.Text = "Информация о системе"; + this.OsInfoBtn.UseVisualStyleBackColor = true; + this.OsInfoBtn.Click += new System.EventHandler(this.OsInfoBtn_Click); + // + // MainMenu + // + this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 21F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(361, 252); + this.Controls.Add(this.OsInfoBtn); + this.Controls.Add(this.FileExtensionTest); + this.Controls.Add(this.SimpleMapperTest); + this.Controls.Add(this.CountValueTest); + this.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "MainMenu"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Главное меню"; + this.ResumeLayout(false); + + } + + #endregion + + private Button CountValueTest; + private Button SimpleMapperTest; + private Button FileExtensionTest; + private Button OsInfoBtn; +} diff --git a/demo/MainMenu.cs b/demo/MainMenu.cs new file mode 100644 index 0000000..e4acabc --- /dev/null +++ b/demo/MainMenu.cs @@ -0,0 +1,32 @@ +namespace demo; +public sealed partial class MainMenu: Form +{ + public MainMenu () + { + InitializeComponent(); + } + + private void button1_Click (object sender, EventArgs e) + { + CountValueTest formCountValueTest = new(); + formCountValueTest.ShowDialog(); + } + + private void SimpleMapperTest_Click (object sender, EventArgs e) + { + SampleMapperTest formSampleMapperTest = new(); + formSampleMapperTest.ShowDialog(); + } + + private void FileExtensionTest_Click (object sender, EventArgs e) + { + FileHashAndMimeType formTest = new(); + formTest.ShowDialog(); + } + + private void OsInfoBtn_Click (object sender, EventArgs e) + { + OsInfoFrm formTest = new(); + formTest.ShowDialog(); + } +} diff --git a/demo/MainMenu.resx b/demo/MainMenu.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/demo/MainMenu.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/demo/OsInfoFrm.Designer.cs b/demo/OsInfoFrm.Designer.cs new file mode 100644 index 0000000..3602c5a --- /dev/null +++ b/demo/OsInfoFrm.Designer.cs @@ -0,0 +1,65 @@ +namespace demo; + +sealed partial class OsInfoFrm +{ + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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; +} \ No newline at end of file diff --git a/demo/OsInfoFrm.cs b/demo/OsInfoFrm.cs new file mode 100644 index 0000000..f92bea5 --- /dev/null +++ b/demo/OsInfoFrm.cs @@ -0,0 +1,28 @@ +using anbs_cp.OsInfo.Classes; + +using Newtonsoft.Json; + +namespace demo; +public sealed partial class OsInfoFrm: Form +{ + public OsInfoFrm () + { + InitializeComponent(); + } + + private void OsInfoFrm_Load (object sender, EventArgs e) + { + textBox.Text = @"Процессор(ы) | "; + textBox.Text += JsonConvert.SerializeObject(OsInfo.Processors); + textBox.Text += @"Оперативная память | "; + textBox.Text += JsonConvert.SerializeObject(OsInfo.RAM); + textBox.Text += @"Видеокарта | "; + textBox.Text += JsonConvert.SerializeObject(OsInfo.Videos); + textBox.Text += @"Диски | "; + textBox.Text += JsonConvert.SerializeObject(OsInfo.Drives); + textBox.Text += @"Windows | "; + textBox.Text += JsonConvert.SerializeObject(OsInfo.Windows); + textBox.Text += @"Net | "; + textBox.Text += JsonConvert.SerializeObject(OsInfo.Net); + } +} diff --git a/demo/OsInfoFrm.resx b/demo/OsInfoFrm.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/demo/OsInfoFrm.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/demo/Program.cs b/demo/Program.cs index 47c0157..44dabc6 100644 --- a/demo/Program.cs +++ b/demo/Program.cs @@ -1,15 +1,14 @@ -namespace demo +namespace demo; + +internal static class Program { - internal static class Program + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main () { - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main() - { - ApplicationConfiguration.Initialize(); - Application.Run(new CountValueTest()); - } + ApplicationConfiguration.Initialize(); + Application.Run(new MainMenu()); } } \ No newline at end of file diff --git a/demo/SampleMapperTest.Designer.cs b/demo/SampleMapperTest.Designer.cs new file mode 100644 index 0000000..6b6ca92 --- /dev/null +++ b/demo/SampleMapperTest.Designer.cs @@ -0,0 +1,189 @@ +namespace demo; + +sealed partial class SampleMapperTest +{ + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose (bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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; +} diff --git a/demo/SampleMapperTest.cs b/demo/SampleMapperTest.cs new file mode 100644 index 0000000..0890aa8 --- /dev/null +++ b/demo/SampleMapperTest.cs @@ -0,0 +1,71 @@ +using anbs_cp.Classes; +using Newtonsoft.Json; + +namespace demo; +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 = JsonConvert.SerializeObject(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 serialize2 = JsonConvert.SerializeObject(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; } +} \ No newline at end of file diff --git a/demo/SampleMapperTest.resx b/demo/SampleMapperTest.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/demo/SampleMapperTest.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/demo/demo.csproj b/demo/demo.csproj index 10977d6..d547f4c 100644 --- a/demo/demo.csproj +++ b/demo/demo.csproj @@ -2,15 +2,31 @@ WinExe - net6.0-windows + net8.0-windows7.0 enable true enable Release;Debug.CNF + demo.Program + + + + True + + + + True + + + + Form + + + \ No newline at end of file diff --git a/demo/demo.csproj.DotSettings b/demo/demo.csproj.DotSettings new file mode 100644 index 0000000..632c268 --- /dev/null +++ b/demo/demo.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp120 \ No newline at end of file