This commit is contained in:
Александр Бабаев 2025-05-05 14:45:58 +03:00
parent 0fb4058186
commit 90dd893f3e
43 changed files with 2501 additions and 63 deletions

4
.editorconfig Normal file
View File

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

View File

@ -2,11 +2,4 @@
ANB Software Components Pack - набор полезных классов C#, которые расширяют возможности языка. Они могут использоваться в приложенях для ОС Widows и серверов на базе этой ОС.
# Лицензия
MIIT
# anbsoftware_componentspack
some classes that extend the capabilities of the C # language
# Лицензия
MIIT

View File

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

View File

@ -26,7 +26,6 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
#endregion
#region Методы
/// <summary>
/// Получает список ключей
/// </summary>
@ -37,25 +36,43 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// Добавляет в список параметр
/// </summary>
/// <param name="keyValue">Параметр</param>
public void Add (KeyValue<TK, TV> keyValue) => _list.Add(keyValue);
public void Add (KeyValue<TK, TV> keyValue)
{
// Проверяет, существует ли ключ в списке
if (Contains(keyValue.Key))
ChangeValue(keyValue);
// Добавляем в список
_list.Add(keyValue);
}
/// <summary>
/// Добавляет в список параметр
/// </summary>
/// <param name="key">Ключ параметра</param>
/// <param name="value">Значение</param>
public void Add (TK key, TV value) => _list.Add(new(key, value));
public void Add (TK key, TV value) => Add(new(key, value));
/// <summary>
/// Добавляет в список некоторый набор элементов
/// </summary>
/// <param name="list">Некоторый набор элементов</param>
public void AddRange (IEnumerable<KeyValue<TK, TV>> list) => _list.AddRange(list);
public void AddRange (IEnumerable<KeyValue<TK, TV>> list)
{
// Получаю список
List<KeyValue<TK, TV>> keyValues = list.ToList();
// Для каждого элемента списка
foreach (KeyValue<TK, TV> keyValue in keyValues)
// - добавляю его в список
Add(keyValue);
}
/// <summary>
/// Изменяет значение
/// </summary>
/// <param name="keyValue">Новое значение</param>
// ReSharper disable once MemberCanBePrivate.Global
public void ChangeValue (KeyValue<TK, TV> keyValue)
{
// Если такой ключ не существует
@ -90,6 +107,7 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// </summary>
/// <param name="key">Ключ</param>
/// <returns>Элемент <see cref="KeyValue{TK,TV}"/></returns>
// ReSharper disable once MemberCanBePrivate.Global
public KeyValue<TK, TV>? GetItem (TK key)
{
// Ищем элемент в списке
@ -125,6 +143,7 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// Удаляет элемент из списка
/// </summary>
/// <param name="keyValue">Элемент</param>
// ReSharper disable once MemberCanBePrivate.Global
public void Remove (KeyValue<TK, TV> keyValue) => _list.Remove(keyValue);
/// <summary>
@ -138,6 +157,7 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// </summary>
/// <param name="keyValue">Элемент</param>
/// <returns>Результат проверки</returns>
// ReSharper disable once MemberCanBePrivate.Global
public bool Contains (KeyValue<TK, TV> keyValue) => _list.Contains(keyValue);
/// <summary>
@ -146,6 +166,7 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
/// <param name="key">Ключ элемента</param>
/// <returns>Результат проверки</returns>
// ReSharper disable once NullableWarningSuppressionIsUsed
// ReSharper disable once MemberCanBePrivate.Global
public bool Contains (TK key) => Keys.Any(keyParam => keyParam!.Equals(key));
/// <summary>
@ -184,14 +205,14 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
result.AddRange(_list.Select(static item => item.Serialize()));
// Вывожу результат
return new SysTextSerializer().Serialize(result);
return new NewtonsoftJsonSerializer().Serialize(result);
}
/// <inheritdoc />
public void Deserialize (string json)
{
// Создаю результат
List<string> result = new SysTextSerializer().Deserialize<List<string>>(json) ?? [];
List<string> result = new NewtonsoftJsonSerializer().Deserialize<List<string>>(json) ?? [];
// Очищаю список
_list.Clear();

View File

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

View File

@ -32,7 +32,7 @@ public static class LikeDelphi
/// <param name="str">Строка, которую нужно разбить</param>
/// <param name="delimiter">Символ-делитель строки</param>
/// <returns>Массив строк</returns>
public static List<string> ParseString (string str, char delimiter) => str.Split(delimiter).ToList();
public static List<string> ParseString (string str, char delimiter) => [.. str.Split(delimiter)];
/// <summary>
/// Переименовываю файл

View File

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

View File

@ -35,6 +35,13 @@ public static class FileExtension
public static FileHash GetHash (string fileName) =>
new(fileName);
/// <summary>
/// Получение содержимого файла
/// </summary>
/// <param name="fileName">Имя файла</param>
/// <returns>Содержимое файла</returns>
public static byte[] GetFileContent (string fileName) => File.ReadAllBytes(fileName);
#region Write
/// <summary>
/// Записывает данные <paramref name="data"/> в текстовый файл <paramref name="fileName"/>

View File

@ -20,4 +20,50 @@ public static class GuidExtensions
/// <param name="g">Guid</param>
/// <returns>Guid пуст (null) или равен Guid.Empty</returns>
public static bool IsNullOrEmpty (this Guid g) => g == Guid.Empty;
/// <summary>
/// Генерирует <see cref="Guid"/>, удовлетворяющий условию <paramref name="predicate"/>
/// </summary>
/// <param name="predicate">Условие генерации <see cref="Guid"/></param>
/// <returns>Новый <see cref="Guid"/></returns>
public static Guid GenerateGuid (Func<Guid, bool> predicate)
{
// Задаю GUID
Guid guid;
// Выполняй
do
{
// - генерируй GUID
guid = Guid.NewGuid();
}
// - пока не выполнено условие
while (!predicate(guid));
// Возвращаю сгенерированный GUID
return guid;
}
/// <summary>
/// Генерирует <see cref="Guid"/>, удовлетворяющий условию <paramref name="asyncPredicate"/>
/// </summary>
/// <param name="asyncPredicate">Условие генерации <see cref="Guid"/></param>
/// <returns>Новый <see cref="Guid"/></returns>
public static async Task<Guid> GenerateGuidAsync (Func<Guid, Task<bool>> asyncPredicate)
{
// Задаю GUID
Guid guid;
// Выполняй
do
{
// - генерируй GUID
guid = Guid.NewGuid();
}
// - пока не выполнено условие
while (!await asyncPredicate(guid));
// Возвращаю сгенерированный GUID
return guid;
}
}

View File

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

View File

@ -1,8 +1,7 @@
using anbs_cp.Classes;
using anbs_cp.Enums;
using anbs_cp.Exceptions;
using ISerializable = anbs_cp.Interfaces.ISerializable;
using anbs_cp.Interfaces;
namespace anbs_cp.Structs;
@ -11,21 +10,22 @@ namespace anbs_cp.Structs;
/// </summary>
/// <typeparam name="TK">Тип ключа</typeparam>
/// <typeparam name="TV">Тип значения</typeparam>
/// <param name="key">Ключ</param>
/// <param name="value">Значение</param>
public struct KeyValue<TK, TV> (TK key, TV? value): ISerializable
/// <param name="Key">Ключ</param>
/// <param name="Value">Значение</param>
public record struct KeyValue<TK, TV> (TK Key, TV? Value): ISerializable
{
#region Свойства
/// <summary>
/// Ключ
/// </summary>
public TK Key { get; set; } = key;
public TK Key { get; private set; } = Key;
/// <summary>
/// Значение
/// </summary>
public TV? Value { get; set; } = value;
// ReSharper disable once MemberCanBePrivate.Global
public TV? Value { get; set; } = Value;
#endregion
@ -40,17 +40,18 @@ public struct KeyValue<TK, TV> (TK key, TV? value): ISerializable
#endregion
#region Реализация интерфейса ISerializable
/// <inheritdoc />
public readonly string Serialize ()
{
// Получаю serialized-значение ключа
string keySerialized = new SysTextSerializer().Serialize(Key);
string keySerialized = new NewtonsoftJsonSerializer().Serialize(Key);
// Исключаю из этого значения = (заменяя на %EQ%)
keySerialized = keySerialized.Replace("=", "%EQ%");
// Получаю serialized-значение значения
string valueSerialized = new SysTextSerializer().Serialize(Value);
string valueSerialized = new NewtonsoftJsonSerializer().Serialize(Value);
// Исключаю из этого значения = (заменяя на %EQ%)
valueSerialized = valueSerialized.Replace("=", "%EQ%");
@ -71,16 +72,16 @@ public struct KeyValue<TK, TV> (TK key, TV? value): ISerializable
"Неверное количество частей! Наверное, лишнее =?");
// Получаю сериализованное представление ключа
string keySerialized = splited[0].Replace("%EQ%", "=");
string keySerialized = splited[0].Replace("%EQ%", "=");
// Получаю сериализованное представление значения
// Получаю сериализованное представление значения
string valueSerialized = splited[1].Replace("%EQ%", "=");
// Десериализую ключ
Key = (new SysTextSerializer().Deserialize<TK>(keySerialized) ?? default(TK))!;
Key = (new NewtonsoftJsonSerializer().Deserialize<TK>(keySerialized) ?? default(TK))!;
// Десериализую значение
Value = new SysTextSerializer().Deserialize<TV>(valueSerialized);
Value = new NewtonsoftJsonSerializer().Deserialize<TV>(valueSerialized);
}
#endregion

View File

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

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>2024.4.8</Version>
<Version>2024.8.18</Version>
<Authors>Александр Бабаев</Authors>
<Product>Набор компонентов ANB Software</Product>
<Description>Библиотека полезных методов языка C#</Description>

View File

@ -8,7 +8,7 @@
<RootNamespace>anbs_cp.Database</RootNamespace>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>ANBSoftware.ComponentsPack.Database</PackageId>
<Version>2024.3.27</Version>
<Version>2024.4.26</Version>
<Company>Александр Бабаев</Company>
<Product>Набор компонентов ANB Software для работы с БД</Product>
<Description>Библиотека полезных методов языка C# для работы с базами данных</Description>
@ -21,7 +21,7 @@
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="MySqlConnector" Version="2.3.6" />
<PackageReference Include="MySqlConnector" Version="2.3.7" />
</ItemGroup>
</Project>

View File

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

View File

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

View File

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

View File

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

View File

@ -16,6 +16,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cposinfo", "anbs_cposi
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cpdb", "anbs_cpdb\anbs_cpdb.csproj", "{3796862F-F181-4A27-92D8-8BF13C4FD711}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "demo2", "demo2\demo2.csproj", "{ED9A2B81-5060-4906-AAC4-88ED1C70211E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F9AFD424-6FCE-465A-8EEF-DA99D3350696}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -41,6 +48,10 @@ Global
{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
{ED9A2B81-5060-4906-AAC4-88ED1C70211E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED9A2B81-5060-4906-AAC4-88ED1C70211E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED9A2B81-5060-4906-AAC4-88ED1C70211E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED9A2B81-5060-4906-AAC4-88ED1C70211E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -5,6 +5,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RA/@EntryIndexedValue">RA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RAM/@EntryIndexedValue">RAM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=URL/@EntryIndexedValue">URL</s:String>
<s:Boolean x:Key="/Default/GrammarAndSpelling/GrammarChecking/Exceptions/=_0412_044B_0447_0438_0441_043B_044F_0435_0442_002C_0020_0435_0441_0442_044C_0020_043B_0438_0020_0445_043E_0442_044F_0020_0431_044B_0020_043E_0434_043D_043E_0020_0438_0437_0020_0431_0443_043B_0435_0432_044B_0445_0020_043F_0435_0440_0435_043C_0435_043D_043D_044B_0445_0020reference_0432_0020_0437_043D_0430_0447_0435_043D_0438_0438/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=abcdefghijkmnopqrstuvwxyz/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ABCDEFGHJKLMNOPQRSTUVWXYZ/@EntryIndexedValue">True</s:Boolean>
@ -15,6 +16,8 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=delim/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Encryptor/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Glendower/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=pjpeg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=splited/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0412_0435_0440_043D_0451_043C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0412_0438_0434_0435_043E_043A_0430_0440_0442_0430/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0414_0435_0441_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_043D_043D_044B_0439/@EntryIndexedValue">True</s:Boolean>
@ -38,6 +41,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043A_0440_0438_043F_0442_043E_0433_0440_0430_0444/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043F_043E_0434_0447_0451_0440_043A_043D_0443_0442_044B_0439/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_043F_0443_0442_0451_043C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0440_0435_0433_0438_0441_0442_0440_043E_0437_0430_0432_0438_0441_0438_043C_043E_0441_0442_044C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0430_0442_043E_0440_0430/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_0438/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_044F/@EntryIndexedValue">True</s:Boolean>

View File

@ -33,6 +33,7 @@ sealed partial class MainMenu
FileExtensionTest = new Button();
OsInfoBtn = new Button();
actionStateSerializerTestBtn = new Button();
stringExtensionTestButton = new Button();
SuspendLayout();
//
// CountValueTest
@ -77,7 +78,7 @@ sealed partial class MainMenu
//
// actionStateSerializerTestBtn
//
actionStateSerializerTestBtn.Location = new Point(12, 254);
actionStateSerializerTestBtn.Location = new Point(12, 242);
actionStateSerializerTestBtn.Name = "actionStateSerializerTestBtn";
actionStateSerializerTestBtn.Size = new Size(335, 51);
actionStateSerializerTestBtn.TabIndex = 4;
@ -85,11 +86,22 @@ sealed partial class MainMenu
actionStateSerializerTestBtn.UseVisualStyleBackColor = true;
actionStateSerializerTestBtn.Click += actionStateSerializerTestBtn_Click;
//
// stringExtensionTestButton
//
stringExtensionTestButton.Location = new Point(12, 299);
stringExtensionTestButton.Name = "stringExtensionTestButton";
stringExtensionTestButton.Size = new Size(335, 51);
stringExtensionTestButton.TabIndex = 5;
stringExtensionTestButton.Text = "Тест расширения класса string";
stringExtensionTestButton.UseVisualStyleBackColor = true;
stringExtensionTestButton.Click += stringExtensionTestButton_Click;
//
// MainMenu
//
AutoScaleDimensions = new SizeF(10F, 21F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(361, 327);
ClientSize = new Size(361, 361);
Controls.Add(stringExtensionTestButton);
Controls.Add(actionStateSerializerTestBtn);
Controls.Add(OsInfoBtn);
Controls.Add(FileExtensionTest);
@ -98,7 +110,10 @@ sealed partial class MainMenu
Font = new Font("Times New Roman", 14.25F);
FormBorderStyle = FormBorderStyle.FixedSingle;
Margin = new Padding(4);
MaximizeBox = false;
MinimizeBox = false;
Name = "MainMenu";
ShowIcon = false;
StartPosition = FormStartPosition.CenterScreen;
Text = "Главное меню";
ResumeLayout(false);
@ -111,4 +126,5 @@ sealed partial class MainMenu
private Button FileExtensionTest;
private Button OsInfoBtn;
private Button actionStateSerializerTestBtn;
private Button stringExtensionTestButton;
}

View File

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

View File

@ -0,0 +1,92 @@
namespace demo.TestForms;
sealed partial class ActionStateSerialize
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose (bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent ()
{
textBox1 = new TextBox();
textBox2 = new TextBox();
label1 = new Label();
button1 = new Button();
SuspendLayout();
//
// textBox1
//
textBox1.Location = new Point(24, 12);
textBox1.Name = "textBox1";
textBox1.Size = new Size(209, 23);
textBox1.TabIndex = 0;
//
// textBox2
//
textBox2.Location = new Point(312, 6);
textBox2.Multiline = true;
textBox2.Name = "textBox2";
textBox2.Size = new Size(463, 225);
textBox2.TabIndex = 1;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(24, 65);
label1.Name = "label1";
label1.Size = new Size(38, 15);
label1.TabIndex = 2;
label1.Text = "label1";
//
// button1
//
button1.Location = new Point(24, 111);
button1.Name = "button1";
button1.Size = new Size(75, 23);
button1.TabIndex = 3;
button1.Text = "button1";
button1.UseVisualStyleBackColor = true;
button1.Click += button1_Click;
//
// ActionStateSerialize
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 250);
Controls.Add(button1);
Controls.Add(label1);
Controls.Add(textBox2);
Controls.Add(textBox1);
Name = "ActionStateSerialize";
Text = "Тест сериализации ActionState";
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox textBox1;
private TextBox textBox2;
private Label label1;
private Button button1;
}

View File

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

View File

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

147
demo/TestForms/CountValueTest.Designer.cs generated Normal file
View File

@ -0,0 +1,147 @@
namespace demo.TestForms;
sealed partial class CountValueTest
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose (bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent ()
{
this.InsertDataLabel = new System.Windows.Forms.Label();
this.InsertDataBox = new System.Windows.Forms.TextBox();
this.ResultLabel = new System.Windows.Forms.Label();
this.CalculateButton = new System.Windows.Forms.Button();
this.SelectFormatterLabel = new System.Windows.Forms.Label();
this.SelectFormatterBox = new System.Windows.Forms.ComboBox();
this.calculateConvButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// InsertDataLabel
//
this.InsertDataLabel.AutoSize = true;
this.InsertDataLabel.Location = new System.Drawing.Point(12, 66);
this.InsertDataLabel.Name = "InsertDataLabel";
this.InsertDataLabel.Size = new System.Drawing.Size(341, 17);
this.InsertDataLabel.TabIndex = 0;
this.InsertDataLabel.Text = "&Введите любое целочисленное значение:";
//
// InsertDataBox
//
this.InsertDataBox.Location = new System.Drawing.Point(12, 86);
this.InsertDataBox.Name = "InsertDataBox";
this.InsertDataBox.Size = new System.Drawing.Size(457, 24);
this.InsertDataBox.TabIndex = 1;
this.InsertDataBox.TextChanged += new System.EventHandler(this.InsertDataBox_TextChanged);
//
// ResultLabel
//
this.ResultLabel.Dock = System.Windows.Forms.DockStyle.Bottom;
this.ResultLabel.Location = new System.Drawing.Point(0, 143);
this.ResultLabel.Margin = new System.Windows.Forms.Padding(5);
this.ResultLabel.Name = "ResultLabel";
this.ResultLabel.Padding = new System.Windows.Forms.Padding(5);
this.ResultLabel.Size = new System.Drawing.Size(478, 79);
this.ResultLabel.TabIndex = 2;
this.ResultLabel.Text = "&Вставьте любое целочисленное значение в поле выше и нажмите кнопку \"Вычислить\", " +
"чтобы увидеть результат...";
this.ResultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// CalculateButton
//
this.CalculateButton.Location = new System.Drawing.Point(12, 116);
this.CalculateButton.Name = "CalculateButton";
this.CalculateButton.Size = new System.Drawing.Size(234, 23);
this.CalculateButton.TabIndex = 3;
this.CalculateButton.Text = "В&ычислить обработчиком";
this.CalculateButton.UseVisualStyleBackColor = true;
this.CalculateButton.Click += new System.EventHandler(this.CalculateButton_Click);
//
// SelectFormatterLabel
//
this.SelectFormatterLabel.AutoSize = true;
this.SelectFormatterLabel.Location = new System.Drawing.Point(12, 9);
this.SelectFormatterLabel.Name = "SelectFormatterLabel";
this.SelectFormatterLabel.Size = new System.Drawing.Size(188, 17);
this.SelectFormatterLabel.TabIndex = 4;
this.SelectFormatterLabel.Text = "В&ыберете обработчик:";
//
// SelectFormatterBox
//
this.SelectFormatterBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.SelectFormatterBox.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.SelectFormatterBox.FormattingEnabled = true;
this.SelectFormatterBox.Items.AddRange(new object[] {
"Обработчик счёта",
"Обработчик размера файла"});
this.SelectFormatterBox.Location = new System.Drawing.Point(12, 29);
this.SelectFormatterBox.Name = "SelectFormatterBox";
this.SelectFormatterBox.Size = new System.Drawing.Size(457, 25);
this.SelectFormatterBox.TabIndex = 5;
//
// calculateConvButton
//
this.calculateConvButton.Location = new System.Drawing.Point(252, 116);
this.calculateConvButton.Name = "calculateConvButton";
this.calculateConvButton.Size = new System.Drawing.Size(217, 23);
this.calculateConvButton.TabIndex = 6;
this.calculateConvButton.Text = "&Вычислить конвертером";
this.calculateConvButton.UseVisualStyleBackColor = true;
this.calculateConvButton.Click += new System.EventHandler(this.calculateConvButton_Click);
//
// CountValueTest
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(478, 222);
this.Controls.Add(this.calculateConvButton);
this.Controls.Add(this.SelectFormatterBox);
this.Controls.Add(this.SelectFormatterLabel);
this.Controls.Add(this.CalculateButton);
this.Controls.Add(this.ResultLabel);
this.Controls.Add(this.InsertDataBox);
this.Controls.Add(this.InsertDataLabel);
this.Font = new System.Drawing.Font("Courier New", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "CountValueTest";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Тест модуля форматирования строки";
this.Load += new System.EventHandler(this.CountValueTest_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Label InsertDataLabel;
private TextBox InsertDataBox;
private Label ResultLabel;
private Button CalculateButton;
private Label SelectFormatterLabel;
private ComboBox SelectFormatterBox;
private Button calculateConvButton;
}

View File

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

View File

@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,125 @@
namespace demo.TestForms;
sealed partial class FileHashAndMimeType
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose (bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent ()
{
this.ResultLabel = new System.Windows.Forms.Label();
this.SelectFileLabel = new System.Windows.Forms.Label();
this.fileNameEdt = new System.Windows.Forms.TextBox();
this.ViewButton = new System.Windows.Forms.Button();
this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
this.topPanel = new System.Windows.Forms.Panel();
this.topPanel.SuspendLayout();
this.SuspendLayout();
//
// ResultLabel
//
this.ResultLabel.Dock = System.Windows.Forms.DockStyle.Fill;
this.ResultLabel.Location = new System.Drawing.Point(0, 0);
this.ResultLabel.Margin = new System.Windows.Forms.Padding(5);
this.ResultLabel.Name = "ResultLabel";
this.ResultLabel.Padding = new System.Windows.Forms.Padding(5);
this.ResultLabel.Size = new System.Drawing.Size(412, 428);
this.ResultLabel.TabIndex = 2;
this.ResultLabel.Text = "В&ыберете файл (введите ипя файла с полным путём вверху или с помощью диалога, на" +
"жав \"Обзор\")...";
this.ResultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// SelectFileLabel
//
this.SelectFileLabel.AutoSize = true;
this.SelectFileLabel.Location = new System.Drawing.Point(3, 11);
this.SelectFileLabel.Name = "SelectFileLabel";
this.SelectFileLabel.Size = new System.Drawing.Size(134, 17);
this.SelectFileLabel.TabIndex = 4;
this.SelectFileLabel.Text = "В&ыберете файл:";
//
// fileNameEdt
//
this.fileNameEdt.Location = new System.Drawing.Point(3, 38);
this.fileNameEdt.Name = "fileNameEdt";
this.fileNameEdt.Size = new System.Drawing.Size(288, 24);
this.fileNameEdt.TabIndex = 5;
this.fileNameEdt.TextChanged += new System.EventHandler(this.fileNameEdt_TextChanged);
//
// ViewButton
//
this.ViewButton.Location = new System.Drawing.Point(297, 39);
this.ViewButton.Name = "ViewButton";
this.ViewButton.Size = new System.Drawing.Size(103, 23);
this.ViewButton.TabIndex = 3;
this.ViewButton.Text = "&Обзор";
this.ViewButton.UseVisualStyleBackColor = true;
this.ViewButton.Click += new System.EventHandler(this.ViewButton_Click);
//
// openFileDialog
//
this.openFileDialog.AddToRecent = false;
this.openFileDialog.Filter = "Все файлы|*.*";
this.openFileDialog.FileOk += new System.ComponentModel.CancelEventHandler(this.openFileDialog_FileOk);
//
// topPanel
//
this.topPanel.Controls.Add(this.SelectFileLabel);
this.topPanel.Controls.Add(this.ViewButton);
this.topPanel.Controls.Add(this.fileNameEdt);
this.topPanel.Dock = System.Windows.Forms.DockStyle.Top;
this.topPanel.Location = new System.Drawing.Point(0, 0);
this.topPanel.Name = "topPanel";
this.topPanel.Size = new System.Drawing.Size(412, 74);
this.topPanel.TabIndex = 6;
//
// FileHashAndMimeType
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(412, 428);
this.Controls.Add(this.topPanel);
this.Controls.Add(this.ResultLabel);
this.Font = new System.Drawing.Font("Courier New", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FileHashAndMimeType";
this.ShowIcon = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Получение хэша и MIME-типа файла";
this.topPanel.ResumeLayout(false);
this.topPanel.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private Label ResultLabel;
private Label SelectFileLabel;
private TextBox fileNameEdt;
private Button ViewButton;
private OpenFileDialog openFileDialog;
private Panel topPanel;
}

View File

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

View File

@ -0,0 +1,63 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="openFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

65
demo/TestForms/OsInfoFrm.Designer.cs generated Normal file
View File

@ -0,0 +1,65 @@
namespace demo.TestForms;
sealed partial class OsInfoFrm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose (bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent ()
{
this.textBox = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// textBox
//
this.textBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.textBox.Location = new System.Drawing.Point(0, 0);
this.textBox.Multiline = true;
this.textBox.Name = "textBox";
this.textBox.Size = new System.Drawing.Size(1029, 510);
this.textBox.TabIndex = 0;
//
// OsInfoFrm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1029, 510);
this.Controls.Add(this.textBox);
this.Font = new System.Drawing.Font("Courier New", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "OsInfoFrm";
this.Text = "Информация о системе";
this.Load += new System.EventHandler(this.OsInfoFrm_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private TextBox textBox;
}

View File

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

View File

@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,189 @@
namespace demo.TestForms;
sealed partial class SampleMapperTest
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose (bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent ()
{
this.DemoBoolEdt = new System.Windows.Forms.CheckBox();
this.DemoStringEdt = new System.Windows.Forms.TextBox();
this.DemoIntEdt = new System.Windows.Forms.NumericUpDown();
this.DemoDateTimeEdt = new System.Windows.Forms.DateTimePicker();
this.MapBtn = new System.Windows.Forms.Button();
this.ResultArea = new System.Windows.Forms.TextBox();
this.DemoStringLabel = new System.Windows.Forms.Label();
this.DemoIntLabel = new System.Windows.Forms.Label();
this.DemoDateTimeLabel = new System.Windows.Forms.Label();
this.MapModeEdit = new System.Windows.Forms.ComboBox();
this.MapModeLabel = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.DemoIntEdt)).BeginInit();
this.SuspendLayout();
//
// DemoBoolEdt
//
this.DemoBoolEdt.AutoSize = true;
this.DemoBoolEdt.Location = new System.Drawing.Point(32, 144);
this.DemoBoolEdt.Name = "DemoBoolEdt";
this.DemoBoolEdt.Size = new System.Drawing.Size(65, 25);
this.DemoBoolEdt.TabIndex = 0;
this.DemoBoolEdt.Text = "Bool";
this.DemoBoolEdt.UseVisualStyleBackColor = true;
//
// DemoStringEdt
//
this.DemoStringEdt.Location = new System.Drawing.Point(32, 42);
this.DemoStringEdt.Name = "DemoStringEdt";
this.DemoStringEdt.Size = new System.Drawing.Size(737, 29);
this.DemoStringEdt.TabIndex = 1;
//
// DemoIntEdt
//
this.DemoIntEdt.Location = new System.Drawing.Point(32, 109);
this.DemoIntEdt.Name = "DemoIntEdt";
this.DemoIntEdt.Size = new System.Drawing.Size(737, 29);
this.DemoIntEdt.TabIndex = 2;
//
// DemoDateTimeEdt
//
this.DemoDateTimeEdt.CustomFormat = "dd.MM.yyyy HH:mm:ss";
this.DemoDateTimeEdt.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
this.DemoDateTimeEdt.Location = new System.Drawing.Point(32, 193);
this.DemoDateTimeEdt.Name = "DemoDateTimeEdt";
this.DemoDateTimeEdt.Size = new System.Drawing.Size(737, 29);
this.DemoDateTimeEdt.TabIndex = 3;
//
// MapBtn
//
this.MapBtn.Location = new System.Drawing.Point(32, 306);
this.MapBtn.Name = "MapBtn";
this.MapBtn.Size = new System.Drawing.Size(737, 57);
this.MapBtn.TabIndex = 5;
this.MapBtn.Text = "СВЯЗАТЬ";
this.MapBtn.UseVisualStyleBackColor = true;
this.MapBtn.Click += new System.EventHandler(this.MapBtn_Click);
//
// ResultArea
//
this.ResultArea.Dock = System.Windows.Forms.DockStyle.Right;
this.ResultArea.Location = new System.Drawing.Point(819, 0);
this.ResultArea.Multiline = true;
this.ResultArea.Name = "ResultArea";
this.ResultArea.ReadOnly = true;
this.ResultArea.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.ResultArea.Size = new System.Drawing.Size(332, 378);
this.ResultArea.TabIndex = 6;
//
// DemoStringLabel
//
this.DemoStringLabel.AutoSize = true;
this.DemoStringLabel.Location = new System.Drawing.Point(32, 18);
this.DemoStringLabel.Name = "DemoStringLabel";
this.DemoStringLabel.Size = new System.Drawing.Size(54, 21);
this.DemoStringLabel.TabIndex = 7;
this.DemoStringLabel.Text = "String";
//
// DemoIntLabel
//
this.DemoIntLabel.AutoSize = true;
this.DemoIntLabel.Location = new System.Drawing.Point(32, 85);
this.DemoIntLabel.Name = "DemoIntLabel";
this.DemoIntLabel.Size = new System.Drawing.Size(30, 21);
this.DemoIntLabel.TabIndex = 8;
this.DemoIntLabel.Text = "Int";
//
// DemoDateTimeLabel
//
this.DemoDateTimeLabel.AutoSize = true;
this.DemoDateTimeLabel.Location = new System.Drawing.Point(32, 169);
this.DemoDateTimeLabel.Name = "DemoDateTimeLabel";
this.DemoDateTimeLabel.Size = new System.Drawing.Size(81, 21);
this.DemoDateTimeLabel.TabIndex = 9;
this.DemoDateTimeLabel.Text = "DateTime";
//
// MapModeEdit
//
this.MapModeEdit.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.MapModeEdit.FormattingEnabled = true;
this.MapModeEdit.Items.AddRange(new object[] {
"Full",
"Not null",
"Not default",
"Not null or default"});
this.MapModeEdit.Location = new System.Drawing.Point(32, 254);
this.MapModeEdit.Name = "MapModeEdit";
this.MapModeEdit.Size = new System.Drawing.Size(737, 29);
this.MapModeEdit.TabIndex = 10;
//
// MapModeLabel
//
this.MapModeLabel.AutoSize = true;
this.MapModeLabel.Location = new System.Drawing.Point(32, 230);
this.MapModeLabel.Name = "MapModeLabel";
this.MapModeLabel.Size = new System.Drawing.Size(167, 21);
this.MapModeLabel.TabIndex = 11;
this.MapModeLabel.Text = "Режим связывания:";
//
// SampleMapperTest
//
this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 21F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1151, 378);
this.Controls.Add(this.MapModeLabel);
this.Controls.Add(this.MapModeEdit);
this.Controls.Add(this.DemoDateTimeLabel);
this.Controls.Add(this.DemoIntLabel);
this.Controls.Add(this.DemoStringLabel);
this.Controls.Add(this.ResultArea);
this.Controls.Add(this.MapBtn);
this.Controls.Add(this.DemoDateTimeEdt);
this.Controls.Add(this.DemoIntEdt);
this.Controls.Add(this.DemoStringEdt);
this.Controls.Add(this.DemoBoolEdt);
this.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Margin = new System.Windows.Forms.Padding(4);
this.Name = "SampleMapperTest";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Тест класса SampleMapper";
((System.ComponentModel.ISupportInitialize)(this.DemoIntEdt)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private CheckBox DemoBoolEdt;
private TextBox DemoStringEdt;
private NumericUpDown DemoIntEdt;
private DateTimePicker DemoDateTimeEdt;
private Button MapBtn;
private TextBox ResultArea;
private Label DemoStringLabel;
private Label DemoIntLabel;
private Label DemoDateTimeLabel;
private ComboBox MapModeEdit;
private Label MapModeLabel;
}

View File

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

View File

@ -0,0 +1,60 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,125 @@
namespace demo.TestForms;
partial class StringExtensionTest
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose (bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent ()
{
stringInputLabel = new Label();
stringInput = new TextBox();
replaceInput = new TextBox();
replaceInputLabel = new Label();
resultLabel = new Label();
doItButton = new Button();
SuspendLayout();
//
// stringInputLabel
//
stringInputLabel.AutoSize = true;
stringInputLabel.Location = new Point(12, 9);
stringInputLabel.Name = "stringInputLabel";
stringInputLabel.Size = new Size(119, 17);
stringInputLabel.TabIndex = 0;
stringInputLabel.Text = "&Введите строку:";
//
// stringInput
//
stringInput.Location = new Point(12, 29);
stringInput.Name = "stringInput";
stringInput.Size = new Size(1005, 26);
stringInput.TabIndex = 1;
//
// replaceInput
//
replaceInput.Location = new Point(12, 89);
replaceInput.Multiline = true;
replaceInput.Name = "replaceInput";
replaceInput.Size = new Size(1005, 307);
replaceInput.TabIndex = 2;
//
// replaceInputLabel
//
replaceInputLabel.AutoSize = true;
replaceInputLabel.Location = new Point(12, 69);
replaceInputLabel.Name = "replaceInputLabel";
replaceInputLabel.Size = new Size(235, 17);
replaceInputLabel.TabIndex = 3;
replaceInputLabel.Text = "&Введите массив замен (что=чем):";
//
// resultLabel
//
resultLabel.Dock = DockStyle.Bottom;
resultLabel.Location = new Point(0, 454);
resultLabel.Name = "resultLabel";
resultLabel.Padding = new Padding(10);
resultLabel.Size = new Size(1025, 184);
resultLabel.TabIndex = 4;
resultLabel.Text = "&Введите данные и нажмите кнопку «Преобразовать», чтобы увидеть здесь резкльтат...";
//
// doItButton
//
doItButton.Location = new Point(12, 402);
doItButton.Name = "doItButton";
doItButton.Size = new Size(1005, 43);
doItButton.TabIndex = 5;
doItButton.Text = "&Преобразовать";
doItButton.UseVisualStyleBackColor = true;
doItButton.Click += doItButton_Click;
//
// StringExtensionTest
//
AutoScaleDimensions = new SizeF(9F, 17F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(1025, 638);
Controls.Add(doItButton);
Controls.Add(resultLabel);
Controls.Add(replaceInputLabel);
Controls.Add(replaceInput);
Controls.Add(stringInput);
Controls.Add(stringInputLabel);
Font = new Font("XO Thames", 12F, FontStyle.Regular, GraphicsUnit.Point, 204);
FormBorderStyle = FormBorderStyle.Fixed3D;
Margin = new Padding(4, 3, 4, 3);
MaximizeBox = false;
MinimizeBox = false;
Name = "StringExtensionTest";
ShowIcon = false;
ShowInTaskbar = false;
StartPosition = FormStartPosition.CenterScreen;
Text = "Тест расширения класса string";
ResumeLayout(false);
PerformLayout();
}
#endregion
private Label stringInputLabel;
private TextBox stringInput;
private TextBox replaceInput;
private Label replaceInputLabel;
private Label resultLabel;
private Button doItButton;
}

View File

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

View File

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

View File

@ -24,9 +24,7 @@
</ItemGroup>
<ItemGroup>
<Compile Update="FileHashAndMimeTypeTest.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="TestForms\FileHashAndMimeTypeTest.cs" />
</ItemGroup>
</Project>

49
demo2/Program.cs Normal file
View File

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

16
demo2/demo2.csproj Normal file
View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\anbs_cp\anbs_cp.csproj" />
</ItemGroup>
</Project>