145 lines
4.7 KiB
C#
145 lines
4.7 KiB
C#
using System.Reflection;
|
|
using Pf2e.Web.Helpers.Format;
|
|
|
|
namespace Pf2e.Web.Helpers.Serialization;
|
|
|
|
/// <summary>
|
|
/// Построитель сериализации для сущности.
|
|
/// </summary>
|
|
/// <param name="type">Тип сущности для сериализации.</param>
|
|
public abstract class EntityBuilder(Type type)
|
|
{
|
|
/// <summary>
|
|
/// Тип сущности для сериализации.
|
|
/// </summary>
|
|
public Type EntityType { get; } = type;
|
|
|
|
/// <summary>
|
|
/// Сериализует объект в список групп полей.
|
|
/// </summary>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
public abstract List<SerializationGroup> Compile(object value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Построитель сериализации для типа T.
|
|
/// </summary>
|
|
/// <typeparam name="TEntity">Тип сущности для сериализации.</typeparam>
|
|
public class EntityBuilder<TEntity>() : EntityBuilder(typeof(TEntity))
|
|
where TEntity : class
|
|
{
|
|
/// <summary>
|
|
/// Список групп полей.
|
|
/// </summary>
|
|
public List<FieldGroupDefinition> Groups { get; set; } = [];
|
|
|
|
/// <summary>
|
|
/// Добавляет группу полей в построитель сериализации.
|
|
/// </summary>
|
|
/// <param name="name">Название группы.</param>
|
|
/// <param name="configure">Делегат для настройки группы полей.</param>
|
|
/// <returns>Текущий экземпляр построителя.</returns>
|
|
public EntityBuilder<TEntity> AddGroup(
|
|
string name,
|
|
Action<FieldGroupBuilder<TEntity>> configure
|
|
)
|
|
{
|
|
FieldGroupBuilder<TEntity> groupBuilder = new(name);
|
|
configure(groupBuilder);
|
|
Groups.Add(groupBuilder.Build());
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Добавляет группу полей в построитель сериализации с названием типа.
|
|
/// </summary>
|
|
/// <param name="configure">Делегат для настройки группы полей.</param>
|
|
/// <returns>Текущий экземпляр построителя.</returns>
|
|
public EntityBuilder<TEntity> AddGroup(Action<FieldGroupBuilder<TEntity>> configure)
|
|
{
|
|
return AddGroup(typeof(TEntity).Name, configure);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override List<SerializationGroup> Compile(object value)
|
|
{
|
|
return Groups.Select(group => CompileGroup(group, value)).ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Строит группу полей.
|
|
/// </summary>
|
|
/// <returns>Готовая группа полей.</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Построение поля сериализации.
|
|
/// </summary>
|
|
/// <param name="field">Определение поля.</param>
|
|
/// <param name="value">Значение поля.</param>
|
|
/// <returns>Построенное поле сериализации.</returns>
|
|
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,
|
|
};
|
|
}
|
|
}
|