This commit is contained in:
Александр Бабаев 2024-02-11 11:19:17 +03:00
parent 341b409264
commit a586c5a0f9
7 changed files with 155 additions and 10 deletions

View File

@ -1,5 +1,6 @@
using System.Collections;
using anbs_cp.Interfaces;
using anbs_cp.Structs;
namespace anbs_cp.Classes;
@ -10,7 +11,7 @@ namespace anbs_cp.Classes;
/// <typeparam name="TK">Тип ключа</typeparam>
/// <typeparam name="TV">Тип значения</typeparam>
// ReSharper disable once ClassCanBeSealed.Global
public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>
public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>, ISerializable
{
/// <summary>
/// Хранение значений
@ -171,4 +172,42 @@ public class KeyValueList<TK, TV>: IEnumerable<KeyValue<TK, TV>>
/// <returns><see cref="IEnumerator"/></returns>
IEnumerator IEnumerable.GetEnumerator () => GetEnumerator();
#endregion
#region Реализация интерфейса ISerializable
/// <inheritdoc />
public string Serialize ()
{
// Создаю результат
List<string> result = [];
// Добавляю сериализованные значения
result.AddRange(_list.Select(static item => item.Serialize()));
// Вывожу результат
return new SysTextSerializer().Serialize(result);
}
/// <inheritdoc />
public void Deserialize (string json)
{
// Создаю результат
List<string> result = new SysTextSerializer().Deserialize<List<string>>(json) ?? [];
// Очищаю список
_list.Clear();
// Пробегаю все значения
foreach (string itemString in result)
{
// - создаю новое значение
KeyValue<TK, TV> item = new();
// - десериализую в него элемента
item.Deserialize(itemString);
// - добавляю получившееся в список
_list.Add(item);
}
}
#endregion
}

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>2024.2.6.1</Version>
<Version>2024.2.11</Version>
<Authors>Александр Бабаев</Authors>
<Product>Набор компонентов ANB Software</Product>
<Description>Библиотека полезных методов языка C#</Description>
@ -22,6 +22,7 @@
<AnalysisLevel>6.0</AnalysisLevel>
<RepositoryType>git</RepositoryType>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>Библиотека полезных методов и классов от ANB</Title>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@ -23,6 +23,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0421_043E_0437_0434_0430_0451_043C/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0432_0432_0435_0434_0451_043D/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0432_0438_0434_0435_043E_043A_0430_0440_0442_0435/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_0438/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_044F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0448_0438_0444_0440_043E_0432_0430_043D_0438_044F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0434_0435_0448_0438_0444_0440_043E_0432_0447_0438_043A/@EntryIndexedValue">True</s:Boolean>
@ -31,9 +32,12 @@
<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/=_0441_0435_0440_0438_0430_043B_0438_0437_0430_0442_043E_0440_0430/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_0438/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_0430_0446_0438_044F/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_043D_043D_043E_0433_043E/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_043D_043D_043E_0435/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0435_0440_0438_0430_043B_0438_0437_043E_0432_0430_043D_043D_0443_044E/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0447_0451_0442/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0441_0447_0451_0442_0447_0438_043A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=_0445_044D_0448_0430/@EntryIndexedValue">True</s:Boolean>