using System.Reflection; using System.Linq.Dynamic.Core; using System.Text; using AutobusApi.Application.Common.Models; using AutoMapper; using AutoMapper.QueryableExtensions; using Microsoft.EntityFrameworkCore; using System.Dynamic; namespace AutobusApi.Application.Common.Mappings; public static class MappingExtensions { public static Task> PaginatedListAsync( this IQueryable queryable, int pageNumber, int pageSize) where T : class { return PaginatedList.CreateAsync(queryable.AsNoTracking(), pageNumber, pageSize); } public static Task> ProjectToListAsync( this IQueryable queryable, IConfigurationProvider configuration) where T : class { return queryable.ProjectTo(configuration).AsNoTracking().ToListAsync(); } public static IQueryable ApplySort( this IQueryable entities, string? orderByQueryString) { if (!entities.Any() || String.IsNullOrWhiteSpace(orderByQueryString)) { return entities; } var orderParams = orderByQueryString.Trim().Split(","); var propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); var orderQueryBuilder = new StringBuilder(); foreach (var param in orderParams) { if (string.IsNullOrWhiteSpace(param)) { continue; } var propertyFromQueryName = param[0] == '-' || param[0] == '+' ? param.Substring(1) : param; var objectProperty = propertyInfos.FirstOrDefault(pi => pi.Name.Equals(propertyFromQueryName, StringComparison.InvariantCultureIgnoreCase)); if (objectProperty == null) { continue; } var sortingOrder = param[0] == '-' ? "descending" : "ascending"; orderQueryBuilder.Append($"{objectProperty.Name} {sortingOrder}, "); } var orderQuery = orderQueryBuilder.ToString().TrimEnd(',', ' '); return entities.OrderBy(orderQuery); } public static IQueryable ShapeData( this IQueryable entities, string? fieldsString) { var allProperties = GetAllProperties(); var requiredProperties = GetRequiredProperties(fieldsString, allProperties); return FetchData(entities, requiredProperties); } public static ExpandoObject ShapeData( this T entity, string? fieldsString) { var allProperties = GetAllProperties(); var requiredProperties = GetRequiredProperties(fieldsString, allProperties); return FetchDataForEntity(entity, requiredProperties); } private static IEnumerable GetAllProperties() { return typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); } private static IEnumerable GetRequiredProperties( string? fieldsString, IEnumerable properties) { var requiredProperties = new List(); if (!string.IsNullOrWhiteSpace(fieldsString)) { var fields = fieldsString.Split(',', StringSplitOptions.RemoveEmptyEntries); foreach (var field in fields) { var property = properties.FirstOrDefault(pi => pi.Name.Equals(field.Trim(), StringComparison.InvariantCultureIgnoreCase)); if (property == null) continue; requiredProperties.Add(property); } } else { requiredProperties = properties.ToList(); } return requiredProperties; } private static IQueryable FetchData( IQueryable entities, IEnumerable requiredProperties) { var shapedData = new List(); foreach (var entity in entities) { var shapedObject = FetchDataForEntity(entity, requiredProperties); shapedData.Add(shapedObject); } return shapedData.AsQueryable(); } private static ExpandoObject FetchDataForEntity( T entity, IEnumerable requiredProperties) { var shapedObject = new ExpandoObject(); foreach (var property in requiredProperties) { var objectPropertyValue = property.GetValue(entity); shapedObject.TryAdd(property.Name, objectPropertyValue); } return shapedObject; } }