20250420
This commit is contained in:
@@ -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();
|
||||
}
|
@@ -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();
|
||||
|
222
anbs_cp/Classes/KeyValueOrderedList.cs
Normal file
222
anbs_cp/Classes/KeyValueOrderedList.cs
Normal 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
|
||||
}
|
@@ -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>
|
||||
/// Переименовываю файл
|
||||
|
27
anbs_cp/Enums/ETextTransform.cs
Normal file
27
anbs_cp/Enums/ETextTransform.cs
Normal 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
|
||||
}
|
@@ -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"/>
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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));
|
||||
}
|
@@ -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
|
||||
|
106
anbs_cp/Structs/KeyValueOrdered.cs
Normal file
106
anbs_cp/Structs/KeyValueOrdered.cs
Normal 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
|
||||
}
|
@@ -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>
|
||||
|
Reference in New Issue
Block a user