API для работы со storage-объектами
API для работы со storage-объектами¶
Данное API предназначено для работы со storage-объектами, такими как IDictionary<string, object>
и IList
.
Интерфейс IStoragePathParser
описывает объект, выполняющий синтаксический анализ строкового представления пути в storage-объекте. Интерфейс IStoragePathResolver
описывает объект обеспечивающий выполнение действий (получение и задание значения) с элементами storage-объекта.
Формат пути в storage-объекте¶
Путь может состоять из следующих элементов:
-
Разделителя элементов пути.
В качестве разделителя используется символ точки –
.
.Note
Для экранирования символа используется обратная косая черта –
\
.Note
Не может использоваться в качестве самостоятельного символа. Может располагаться только между ключами и/или индексами или символами перехода к родительскому элементу.
-
Ключа.
Ключ – это строка, по которой выполняется доступ к объекту, расположенному в объекте, реализующем интерфейс
IDictionary<string, object>
.Примеры:
Key
,\.key
,\.
. -
Индекса.
Индекс – это порядковый номер элемента, расположенного в объекте, реализующем интерфейс
IList
.Примеры:
[0]
,[0][1]
,Key[0]
. -
Подстановочного символа.
-
[]
– указывает на необходимость обхода всех элементов списка.Примеры:
[]
,[][]
,Key[]
. -
^
– указывает на необходимость перехода к родительскому элементу пути.Примеры:
Key.^
,[].^
.
-
Примеры работы с путями¶
В примерах будет использоваться объект:
{
"First": {
"Second": [
{
"Third": [
{
"Forth": "Test11"
},
{
"Forth": "Test12"
}
],
"ID": "ID1"
},
{
"Third": [
{
"Forth": "Test21"
},
{
"Forth": "Test22"
}
],
"ID": "ID2"
}
]
}
}
-
Получение значения по заданному ключу.
Путь:
First
Значение:
{ "Second": [ { "Third": [ { "Forth": "Test11" }, { "Forth": "Test12" } ], "ID": "ID1" }, { "Third": [ { "Forth": "Test21" }, { "Forth": "Test22" } ], "ID": "ID2" } ] }
-
Получение значения по индексу.
Путь:
First.Second[1].Third[1].Forth
Значение: Test22
-
Получение все значенией расположенных в списке.
Путь:
First.Second[].Third[].Forth
Результат выполнения:
Путь по которому расположено значениеЗначение First.Second[0].Third[0].Forth
Test11
First.Second[0].Third[1].Forth
Test12
First.Second[1].Third[0].Forth
Test21
First.Second[1].Third[1].Forth
Test22
-
Обработка пути содержащего переход к родительскому элементу.
-
First.Second[1].Third[1].Forth.^.^.^.ID
Результат выполнения:
Путь по которому расположено значениеЗначение First.Second[1].ID
ID2
-
First.Second[].Third[].Forth.^.^.^.ID
Результат выполнения:
Путь по которому расположено значениеЗначение First.Second[0].ID
ID1
First.Second[1].ID
ID2
-
Использование синтаксического анализатора пути в storage-объекте¶
Пример использования анализатора.
IStoragePathParser parser = new StoragePathParser(); // Объект можно получить из Unity-контейнера по IStoragePathParser.
// Пример пути для объекта, расположенного в табличной секции карточки `Card`.
string path1 = "Sections.KrStages.Rows[0].RuntimeSourceCondition";
// Пример пути для объекта, расположенного в строковой секции карточки `Card`.
string path2= "Sections.KrSecondaryProcesses.Fields.VisibilitySourceCondition";
IReadOnlyList<IStoragePathItem> parseResult1 = parser.Parse(path);
IReadOnlyList<IStoragePathItem> parseResult2 = parser.Parse(path);
Использование объекта, обеспечивающего выполнение действий с элементами storage-объекта¶
IStoragePathResolver
предназначен для получения и присвоения значений по заданонму пути внутри storage-объекта.
IStoragePathParser parser = new StoragePathParser(); // Объект можно получить из Unity-контейнера по IStoragePathParser.
IStoragePathResolver resolver = new StoragePathResolver(); // Объект можно получить из Unity-контейнера по IStoragePathResolver.
Card card = ...GetCard(); // Любой способ получения карточки
// Получаем storage от объекта Card (это может быть также любой объект типа, который реализует IStorageObjectProvider).
IDictionary<string, object> storage = card.GetStorage();
// Путь в storage-объекте.
string path = "Sections.KrStages.Rows[5].RuntimeSourceCondition";
// Анализ пути.
IReadOnlyList<IStoragePathItem> pathParseResult = parser.Parse(path);
// Получение объекта, находящегося в хранилище по заданному пути.
IList<(IReadOnlyList<IStoragePathItem> PathItems, object Value)> result = resolver.Resolve(pathParseResult, storage);
// Если необходимо по данному пути присвоить новый объект/значение, то необходимо использовать метод SetValueWithSuffix.
object newValue = new () { Field1 = "someString" };
resolver.SetValueWithSuffix(pathParseResult, storage, newValue);
// Метод SetValueWithSuffix также позволяет, в случае необходимости,
// добавить суффикс к ключу, по которому будет расположен объект.
string suffix = "my-suffix";
// Если был указан суффикс, т.е. он не является значением null или пустой строкой,
// то объект newValue, который до этого располагался по ключу "RuntimeSourceCondition" (это последний элемент пути),
// будет сохранён по ключу "RuntimeSourceCondition::my-suffix", а ключ "RuntimeSourceCondition" будет удален из storage.
resolver.SetValueWithSuffix(pathParseResult, storage, newValue, suffix);
Использование объекта, который позволяет запоминать и восстанавливать значения из хранилища (storage) по заданным путям.¶
IStorageValuesKeeper
предназначен для того, чтобы запоминать и восстанавливать значения из хранилища по заданным путям.
StoragePathResolveOptions
- опции в виде флагов для определения поведения при разрешении путей.
// Создание объекта StorageValuesKeeper. Такое создание объекта приведено для примера, рекомендуется получать объект из Unity-контейнера по интерфейсу IStorageValuesKeeper.
IStorageValuesKeeper valuesKeeper = new StorageValuesKeeper(new StoragePathParser(), new StoragePathResolver());
// Для использования механизма сохранения/восстановления значений необходимо задать пути, по которым эти значения находятся.
// Например, сохраним некоторые значения для карточки.
var pathsForValuesKeeper = new List<StorageContentMapping>
{
// Значения карточки с прямыми путями.
new() { StoragePath = "Card.Modified" },
// Если точка является не разделителем пути, а входит в состав значения части пути, ее (точку) необходимо экранировать символом '\'.
new() { StoragePath = @"Info.\.importVersion" },
// Файлы карточки
new()
{
// Т.к. файлов может быть несколько, в пути использован wildcard типа '[]'.
StoragePath = "Card.Files[].Card.Version",
// То, что используется wildcard, подразумевает, что по такому пути могут быть несколько значений, следовательно, чтобы их правильно разрешить в дальнейшем,
// необходимо указать путь до уникального (для данной коллекции значений) идентификатора, с которыми значения будут сопоставлены.
// Путь до идентификаторов указывается относительно пути до значений.
IDKeys = new List<string> { "^.RowID" } // В данном случае запись означает, что путь до идентификаторов - "Card.Files[].RowID".
},
// Общие данные сателлитов
new()
{
StoragePath = @"Card.Info.\.satellites[].Modified",
IDKeys = new List<string> { "ID" } // Путь до идентификаторов - "Card.Info.\.satellites[].ID"
},
// Возможно использование нескольких wildcards.
// Файлы сателлитов
new()
{
// Если в пути имеются несколько wildсards типа [], то необходимо задать относительные пути до идентификаторов для каждого wildcard.
// Пути до иентификаторов должны быть в строгом порядке, а именно, первыми должны быть заданы идентификаторы для конечных значений, которые должны быть сохранены,
// в данном случае это коллекция где содержатся поля с ключем "Version", затем для родительских коллекций и так далее если количество wildcards больше.
StoragePath = @"Card.Info.\.satellites[].Files[].Card.Version",
IDKeys = new List<string> {
"^.RowID", // Путь до идентификаторов, которые относятся непосредственно к полям с сохраняемым значением - "Card.Info.\.satellites[].Files[].RowID"
"^.^.^.ID" // Путь до идентификаторов, которые относятся к родительским коллекциям - "Card.Info.\.satellites[].ID"
}
}
};
// Запомнить нужные значения. Метод KeepValues принимает сам объект хранилища, коллекцию путей до значений и опции в виде флагов.
valuesKeeper.KeepValues(
storage,
pathsForValuesKeeper,
// В этом примере опции указывают на то, что при обработке списков внутри хранилища (например, в той части пути, которая содержит wildcard типа []),
// если такой список равен `null`, не будет сенерировано исключение, а значением по такому пути будет являться `null`.
StoragePathResolveOptions.IgnoredNullList);
/* Логика после которой необходимо восстановить запомненные значения. */
...
// Восстановить запомненные значения.
// Если значения были запомнены по путям с использованием wildcards и указанием относительных путей до идентификаторов, то такие значения будут восстановлены
// с учетом этих идентификаторов. Иначе значения будут восстановлены по прямым путям.
// Параметр ignoreNotFound означает, что не требуется генерировать исключение в случае невозможности разрешения пути в переданном хранилище при попытке восстановить значение.
valuesKeeper.RestoreValues(storage, ignoreNotFound: true);
Note
Допустимо, что передаваемый в метод RestoreValues()
объект хранилища может являться объектом, отличным от того, из которого значения были запомнены в методе KeepValues()
.