using System.Reflection;
using Pf2e.Web.Helpers.Format;
namespace Pf2e.Web.Helpers.Serialization;
///
/// Построитель сериализации для сущности.
///
/// Тип сущности для сериализации.
public abstract class EntityBuilder(Type type)
{
///
/// Тип сущности для сериализации.
///
public Type EntityType { get; } = type;
///
/// Сериализует объект в список групп полей.
///
///
///
public abstract List Compile(object value);
}
///
/// Построитель сериализации для типа T.
///
/// Тип сущности для сериализации.
public class EntityBuilder() : EntityBuilder(typeof(TEntity))
where TEntity : class
{
///
/// Список групп полей.
///
public List Groups { get; set; } = [];
///
/// Добавляет группу полей в построитель сериализации.
///
/// Название группы.
/// Делегат для настройки группы полей.
/// Текущий экземпляр построителя.
public EntityBuilder AddGroup(
string name,
Action> configure
)
{
FieldGroupBuilder groupBuilder = new(name);
configure(groupBuilder);
Groups.Add(groupBuilder.Build());
return this;
}
///
/// Добавляет группу полей в построитель сериализации с названием типа.
///
/// Делегат для настройки группы полей.
/// Текущий экземпляр построителя.
public EntityBuilder AddGroup(Action> configure)
{
return AddGroup(typeof(TEntity).Name, configure);
}
///
public override List Compile(object value)
{
return Groups.Select(group => CompileGroup(group, value)).ToList();
}
///
/// Строит группу полей.
///
/// Готовая группа полей.
public SerializationGroup CompileGroup(FieldGroupDefinition groupDefinition, object value)
{
SerializationGroup result = new() { Name = groupDefinition.Name };
foreach (FieldDefinition field in groupDefinition.Fields)
{
PropertyInfo? propertyInfo = groupDefinition.GroupType.GetProperty(field.Name);
if (propertyInfo == null)
continue;
object? fieldValue = propertyInfo.GetValue(value);
result.Fields.Add(CompileField(field, fieldValue));
}
return result;
}
///
/// Построение поля сериализации.
///
/// Определение поля.
/// Значение поля.
/// Построенное поле сериализации.
private SerializationField CompileField(FieldDefinition field, object? value)
{
if (value is null)
{
return new()
{
Name = field.Name,
Type = field.Type.Name,
Value = "null",
IsImplemented = true,
};
}
if (field.ValueFormatter is not null)
{
return new()
{
Name = field.Name,
Type = field.Type.Name,
Value = field.ValueFormatter(value),
IsImplemented = true,
};
}
ValueFormatter? formatter = Formatters.SelectFormatter(value);
if (formatter is not null)
{
return new()
{
Name = field.Name,
Type = field.Type.Name,
Value = formatter.Format(value),
IsImplemented = true,
};
}
return new()
{
Name = field.Name,
Type = field.Type.Name,
Value = value.ToString() ?? "null",
IsImplemented = false,
};
}
}