141 lines
4.3 KiB
C#
141 lines
4.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Pf2e.WPF.EntityViewer.EntityViewStructure;
|
|
|
|
/// <summary>
|
|
/// Класс для построения структуры данных класса.
|
|
/// </summary>
|
|
internal class StructureBuilder
|
|
{
|
|
/// <summary>
|
|
/// Список обработанных объектов.
|
|
/// </summary>
|
|
private readonly List<StructureProcessedObject> _processedObjects = [];
|
|
|
|
/// <summary>
|
|
/// Создание поля структуры.
|
|
/// </summary>
|
|
/// <param name="name">Название поля.</param>
|
|
/// <param name="value">Значение поля.</param>
|
|
/// <param name="depth">Глубина, на котором поле отображается.</param>
|
|
/// <returns>Поле структуры.</returns>
|
|
public StructureFieldComplex Create(string name, object value, int depth = 0)
|
|
{
|
|
_ = RegisterProcessed(value);
|
|
|
|
StructureFieldComplex field = new(this, value, name, depth);
|
|
|
|
CompleteProcessed(value, field);
|
|
|
|
return field;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Регистрация обработанного объекта.
|
|
/// </summary>
|
|
/// <param name="value">Регистрируемый объект.</param>
|
|
/// <returns>`true`, если объект был добавлен; `false`, если объект был добавлен ранее.</returns>
|
|
public bool RegisterProcessed(object value)
|
|
{
|
|
if (_processedObjects.Any(p => p.Value == value))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
StructureProcessedObject processed = new(value);
|
|
|
|
_processedObjects.Add(processed);
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Дополнить обработанный объект.
|
|
/// </summary>
|
|
/// <param name="value">Значение.</param>
|
|
/// <param name="field">Поле объекта.</param>
|
|
public void CompleteProcessed(object value, StructureFieldComplex field)
|
|
{
|
|
StructureProcessedObject? q = _processedObjects.FirstOrDefault(p => p.Value == value);
|
|
|
|
if (q == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
q.Field = field;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Выбор поля структуры по значению.
|
|
/// </summary>
|
|
/// <param name="name">Название поля.</param>
|
|
/// <param name="value">Значение поля.</param>
|
|
/// <param name="depth">Глубина, на котором поле отображается.</param>
|
|
/// <returns></returns>
|
|
public StructureField Resolve(string name, object? value, int depth)
|
|
{
|
|
switch (GetFieldType(value))
|
|
{
|
|
case StructureFieldType.Null:
|
|
return new StructureFieldNull(this, name, depth);
|
|
|
|
case StructureFieldType.Primitive:
|
|
return new StructureFieldPrimitive(this, value!, name, depth);
|
|
|
|
case StructureFieldType.Enum:
|
|
return new StructureFieldEnum(this, value!, name, depth);
|
|
|
|
case StructureFieldType.Reference:
|
|
break;
|
|
|
|
case StructureFieldType.Complex:
|
|
default:
|
|
|
|
StructureProcessedObject? processed = _processedObjects.FirstOrDefault(p =>
|
|
p.Value == value
|
|
);
|
|
|
|
if (processed is null)
|
|
{
|
|
return Create(name, value!, depth);
|
|
}
|
|
|
|
StructureFieldReference reference = new(this, name, null, depth);
|
|
processed.AddReference(reference);
|
|
return reference;
|
|
}
|
|
|
|
throw new("Impossible");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Получить тип поля структуры по значению.
|
|
/// </summary>
|
|
/// <param name="value">Значение поля.</param>
|
|
/// <returns>Тип поля структуры.</returns>
|
|
public static StructureFieldType GetFieldType(object? value)
|
|
{
|
|
if (value is null)
|
|
{
|
|
return StructureFieldType.Null;
|
|
}
|
|
|
|
Type type = value.GetType();
|
|
|
|
if (type.IsEnum)
|
|
{
|
|
return StructureFieldType.Enum;
|
|
}
|
|
|
|
if (type.IsPrimitive || type == typeof(string))
|
|
{
|
|
return StructureFieldType.Primitive;
|
|
}
|
|
|
|
return StructureFieldType.Complex;
|
|
}
|
|
}
|