using System.Reflection; using HopFrame.Web.Admin.Attributes; using HopFrame.Web.Admin.Attributes.Classes; using HopFrame.Web.Admin.Models; namespace HopFrame.Web.Admin.Generators.Implementation; internal class AdminContextGenerator : IAdminContextGenerator { private readonly IDictionary _adminPages = new Dictionary(); public IAdminPageGenerator Page() { if (_adminPages.TryGetValue(typeof(TModel), out var pageGenerator)) return pageGenerator as IAdminPageGenerator; var generator = Activator.CreateInstance(typeof(IAdminPageGenerator)) as IAdminPageGenerator; ApplyConfigurationFromAttributes(generator, typeof(TModel).GetCustomAttributes(false)); _adminPages.Add(typeof(TModel), generator); return generator; } public AdminPage CompilePage() { var generator = _adminPages[typeof(TModel)]; if (generator is null) return null; return (generator as AdminPageGenerator)?.Compile(); } public TContext CompileContext() where TContext : AdminPagesContext { var type = typeof(TContext); var compileMethod = typeof(AdminContextGenerator).GetMethod(nameof(CompilePage)); var properties = type.GetProperties(); var context = Activator.CreateInstance(); foreach (var property in properties) { var propertyType = property.PropertyType.GenericTypeArguments[0]; var pageGeneratorType = typeof(AdminPageGenerator<>).MakeGenericType(propertyType); var generatorInstance = Activator.CreateInstance(pageGeneratorType, [propertyType.Name]); var populatorMethod = typeof(AdminContextGenerator) .GetMethod(nameof(ApplyConfigurationFromAttributes))? .MakeGenericMethod(propertyType); populatorMethod?.Invoke(this, [generatorInstance, propertyType.GetCustomAttributes()]); _adminPages.Add(propertyType, generatorInstance); } context.OnModelCreating(this); foreach (var property in properties) { var modelType = property.PropertyType.GenericTypeArguments[0]; var method = compileMethod?.MakeGenericMethod(modelType); property.SetValue(context, method?.Invoke(this, [])); } return context; } public void ApplyConfigurationFromAttributes(IAdminPageGenerator generator, object[] attributes) { if (attributes.Any(a => a is AdminNameAttribute)) { var attribute = attributes.Single(a => a is AdminNameAttribute) as AdminNameAttribute; generator.Title(attribute?.Name); } if (attributes.Any(a => a is AdminDescriptionAttribute)) { var attribute = attributes.Single(a => a is AdminDescriptionAttribute) as AdminDescriptionAttribute; generator.Description(attribute?.Description); } if (attributes.Any(a => a is AdminPermissionsAttribute)) { var attribute = attributes.Single(a => a is AdminPermissionsAttribute) as AdminPermissionsAttribute; generator.CreatePermission(attribute?.Permissions.Create); generator.UpdatePermission(attribute?.Permissions.Update); generator.ViewPermission(attribute?.Permissions.View); generator.DeletePermission(attribute?.Permissions.Delete); } if (attributes.Any(a => a is AdminButtonConfigAttribute)) { var attribute = attributes.Single(a => a is AdminButtonConfigAttribute) as AdminButtonConfigAttribute; generator.ShowCreateButton(attribute?.ShowCreateButton == true); generator.ShowUpdateButton(attribute?.ShowUpdateButton == true); generator.ShowDeleteButton(attribute?.ShowDeleteButton == true); } } }