using System.Linq.Expressions; using System.Reflection; namespace Pf2e.Web.Helpers; /// /// Построитель сериализации для типа T. /// /// Тип сущности для сериализации. public class SerializationBuilder where T : class { /// /// Список групп полей. /// public List Groups { get; set; } = []; /// /// Форматтер полей сущности. /// protected EntityFieldFormatter FieldFormatter { get; } = new(); /// /// Добавляет группу полей в построитель сериализации. /// /// Название группы. /// Делегат для настройки группы полей. /// Текущий экземпляр построителя. public SerializationBuilder AddGroup(string name, Action> configure) { FieldGroupBuilder groupBuilder = new(name); configure(groupBuilder); Groups.Add(groupBuilder.Build()); return this; } /// /// Добавляет группу полей в построитель сериализации с названием типа. /// /// Делегат для настройки группы полей. /// Текущий экземпляр построителя. public SerializationBuilder AddGroup(Action> configure) { return AddGroup(typeof(T).Name, configure); } /// /// Построитель группы полей для типа TField. /// /// Тип сущности для группы полей. public class FieldGroupBuilder(string name) where TField : class { private readonly FieldGroup _group = new() { Name = name }; /// /// Добавляет поле в группу. /// /// Лямбда-выражение для получения поля. /// Текущий экземпляр построителя группы полей. public FieldGroupBuilder AddField(Expression> fieldExpression) { // Получаем информацию о свойстве из выражения MemberExpression? memberExpression = GetMemberExpression(fieldExpression.Body); if (memberExpression == null) { throw new ArgumentException( "Выражение должно быть доступом к свойству", nameof(fieldExpression) ); } PropertyInfo propertyInfo = (PropertyInfo)memberExpression.Member; string fieldName = propertyInfo.Name; Type fieldType = propertyInfo.PropertyType; _group.Fields.Add(new() { Name = fieldName, Type = fieldType }); return this; } /// /// Устанавливает форматтер значения для последнего добавленного поля. /// /// Функция форматирования значения. /// Текущий экземпляр построителя группы полей. public FieldGroupBuilder SetValueFormatter(Func valueFormatter) { _group.Fields.Last().ValueFormatter = valueFormatter; return this; } /// /// Строит группу полей. /// /// Готовая группа полей. public FieldGroup Build() => _group; /// /// Получает MemberExpression из тела лямбда-выражения. /// /// Тело выражения. /// MemberExpression или null, если не удалось получить. private static MemberExpression? GetMemberExpression(Expression expression) { return expression switch { MemberExpression memberExpression => memberExpression, UnaryExpression { NodeType: ExpressionType.Convert } unaryExpression => unaryExpression.Operand as MemberExpression, _ => null, }; } } /// /// Группа полей. /// public class FieldGroup { /// /// Название группы. /// public string Name { get; set; } = string.Empty; /// /// Список полей в группе. /// public List Fields { get; set; } = []; } /// /// Информация о поле. /// public class FieldBuilderDefinition { /// /// Название поля. /// public string Name { get; set; } = string.Empty; /// /// Тип поля. /// public required Type Type { get; set; } /// /// Форматтер значения поля. /// public Func? ValueFormatter { get; set; } = null; } }