using System.Collections; using System.Reflection; using Pf2e.Common; using Pf2e.Database.Model; using Pf2e.Database.Model.Base; using Pf2e.Database.Model.Common.I18n; using Pf2e.Database.Model.Enum; namespace Pf2e.Web.Helpers; /// /// Сериализатор сущности для отображения на веб-странице. /// public class EntitySerializer { /// /// Результат сериализации сущности. /// public class SerializationResult { public List Groups { get; set; } = []; } /// /// Группа полей. /// public class FieldGroup { public string Name { get; set; } = string.Empty; public List Fields { get; set; } = []; } /// /// Информация о поле. /// public class FieldInfo { public string Name { get; set; } = string.Empty; public string Type { get; set; } = string.Empty; public object? Value { get; set; } public string DisplayValue { get; set; } = string.Empty; public bool IsImplemented { get; set; } = true; } /// /// Сериализовать FullEntity. /// public SerializationResult Serialize(FullEntity fullEntity) { SerializationResult result = new(); // Группа для основных полей Entity FieldGroup entityGroup = new() { Name = "Основные поля" }; AddFieldsToGroup(entityGroup, fullEntity.Entity); result.Groups.Add(entityGroup); // Группа для полей IEntity (SubEntity) if (fullEntity.SubEntity != null) { FieldGroup subEntityGroup = new() { Name = "Поля " + fullEntity.SubEntity.GetType().Name, }; AddFieldsToGroup(subEntityGroup, fullEntity.SubEntity); result.Groups.Add(subEntityGroup); } // Группа для ссылок FieldGroup referencesGroup = new() { Name = "Ссылки" }; AddReferencesToGroup(referencesGroup, fullEntity); result.Groups.Add(referencesGroup); return result; } /// /// Добавить поля объекта в группу. /// private void AddFieldsToGroup(FieldGroup group, object obj) { Type type = obj.GetType(); PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo property in properties) { // Пропускаем навигационные свойства Entity if (property.Name == "Entity") continue; FieldInfo fieldInfo = new() { Name = property.Name, Type = GetTypeDisplayName(property.PropertyType), Value = property.GetValue(obj), }; // Обработка значения для отображения var (displayValue, isImplemented) = FormatValue(fieldInfo.Value); fieldInfo.DisplayValue = displayValue; fieldInfo.IsImplemented = isImplemented; group.Fields.Add(fieldInfo); } } /// /// Добавить ссылки в группу. /// private void AddReferencesToGroup(FieldGroup group, FullEntity fullEntity) { // Добавляем информацию о связанных сущностях Entity entity = fullEntity.Entity; // Traits if (entity.Traits?.Any() == true) { var (displayValue, isImplemented) = FormatValue(entity.Traits); group.Fields.Add( new FieldInfo { Name = "Traits", Type = "ICollection", Value = entity.Traits, DisplayValue = displayValue, IsImplemented = isImplemented, } ); } // Keywords if (entity.Keywords?.Any() == true) { var (displayValue, isImplemented) = FormatValue(entity.Keywords); group.Fields.Add( new FieldInfo { Name = "Keywords", Type = "ICollection", Value = entity.Keywords, DisplayValue = displayValue, IsImplemented = isImplemented, } ); } // Sources if (entity.Sources?.Any() == true) { var (displayValue, isImplemented) = FormatValue(entity.Sources); group.Fields.Add( new FieldInfo { Name = "Sources", Type = "ICollection", Value = entity.Sources, DisplayValue = displayValue, IsImplemented = isImplemented, } ); } // Externals if (entity.Externals?.Any() == true) { var (displayValue, isImplemented) = FormatValue(entity.Externals); group.Fields.Add( new() { Name = "Externals", Type = "ICollection", Value = entity.Externals, DisplayValue = displayValue, IsImplemented = isImplemented, } ); } } /// /// Получить отображаемое имя типа. /// private string GetTypeDisplayName(Type type) { if (type.IsEnum) return "enum"; return type.Name; } /// /// Форматировать значение для отображения. /// private (string displayValue, bool isImplemented) FormatValue(object? value) { if (value == null) return ("null", true); Type type = value.GetType(); // Обработка перечислений if (type.IsEnum) { Enum enumValue = (Enum)value; return ($"{enumValue} ({(int)(object)enumValue})", true); } // Обработка примитивных типов if (type.IsPrimitive || type == typeof(string) || type == typeof(decimal)) { return (value.ToString() ?? "null", true); } // Обработка IEntity if (typeof(IEntity).IsAssignableFrom(type)) { var entity = (IEntity)value; var entityType = entity.Entity.Type; var slug = entity.Entity.Slug; var name = entity.Entity.Name[LocaleType.English]; return ($"{name}", true); } // Обработка коллекций if (typeof(IEnumerable).IsAssignableFrom(type) && type != typeof(string)) { var collection = (IEnumerable)value; var items = new List(); bool allImplemented = true; foreach (var item in collection) { var (itemDisplay, itemImplemented) = FormatValue(item); items.Add(itemDisplay); if (!itemImplemented) allImplemented = false; } if (items.Count == 0) return ("(empty)", true); return (string.Join(", ", items), allImplemented); } // Для остальных сложных объектов return ($"[{type.Name}] - НЕ РЕАЛИЗОВАНО", false); } }