Initial commit - ECommerce project
This commit is contained in:
Executable
+28
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentEmail.Core" Version="3.0.2" />
|
||||
<PackageReference Include="FluentEmail.Smtp" Version="3.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.12.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../ECommerce.Contracts/ECommerce.Contracts.csproj" />
|
||||
<ProjectReference Include="../ECommerce.Domain/ECommerce.Domain.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\SharedLogic\Generic\Generic.csproj" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,236 @@
|
||||
using System;
|
||||
using Commerce.Contracts.DTOs;
|
||||
using Commerce.Domain;
|
||||
using Commerce.Domain.Entities;
|
||||
using Generic.Contracts.Generics;
|
||||
using Generic.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Commerce.Core.Services;
|
||||
|
||||
public class CategoryService
|
||||
{
|
||||
|
||||
private readonly Context context;
|
||||
|
||||
public CategoryService(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task CreateCategory(CategoryVM categoryVM)
|
||||
{
|
||||
var category = Category.ToEntity(categoryVM);
|
||||
await context.Categories.AddAsync(category);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task UpdateCategory(CategoryVM categoryVM)
|
||||
{
|
||||
if (categoryVM.Id == null) throw new ArgumentException("Category ID is required for update.");
|
||||
|
||||
var existingCategory = await context.Categories
|
||||
.FirstOrDefaultAsync(x => x.Id == categoryVM.Id);
|
||||
|
||||
if (existingCategory == null) throw new KeyNotFoundException("Category not found.");
|
||||
|
||||
// Update properties
|
||||
existingCategory.Translations = categoryVM.Translations?.Select(t => new CategoryTranslation
|
||||
{
|
||||
Language = t.Language,
|
||||
Info = new CategoryInfo
|
||||
{
|
||||
Name = t.Info.Name,
|
||||
Description = t.Info.Description,
|
||||
TechnicalDetails = t.Info.TechnicalDetails?.Select(td => new Commerce.Domain.Entities.TechnicalDetail { Key = td.Key, Value = td.Value }).ToList() ?? new()
|
||||
}
|
||||
}).ToList() ?? new();
|
||||
|
||||
existingCategory.Photos = categoryVM.Photos ?? Array.Empty<string>();
|
||||
existingCategory.ParentCategoryId = categoryVM.ParentCategoryId;
|
||||
existingCategory.IsBundle = categoryVM.IsBundle;
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task RemoveCategory(Guid id)
|
||||
{
|
||||
var category = await context.Categories.FindAsync(id);
|
||||
if (category != null) context.Categories.Remove(category);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<CategoryVM> GetCategory(Guid id)
|
||||
{
|
||||
var category = await context.Categories.FindAsync(id);
|
||||
return category != null ? Category.ToVM(category) : new CategoryVM();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<(List<CategoryVM>, int)> FetchCategory(
|
||||
CategoryFilter categoryFilter,
|
||||
Pagination pagination
|
||||
)
|
||||
{
|
||||
var query = context.Categories.AsQueryable();
|
||||
query = query.ApplyAdvancedFilter(categoryFilter);
|
||||
// query = query.ApplySorting(sortBy);
|
||||
if (categoryFilter.Random ?? false)
|
||||
{
|
||||
query = query.OrderBy(x => Guid.NewGuid());
|
||||
}
|
||||
else
|
||||
{
|
||||
// query = query.ApplySorting(sortBy);
|
||||
}
|
||||
var count = query.Count();
|
||||
query = query.Paginate(pagination);
|
||||
|
||||
var lang = categoryFilter.Language;
|
||||
return (await query.Select(x => Category.ToVM(x, lang)).ToListAsync(), count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<List<Category>> GetAllCategories(string name = "")
|
||||
{
|
||||
|
||||
var categories = await context.Categories.ToListAsync();
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
categories = categories.Where(x => x.Translations.Any(t => t.Info.Name.Contains(name, StringComparison.OrdinalIgnoreCase))).ToList();
|
||||
return categories;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<Category>> GetAllCategories_Tree(string name = "")
|
||||
{
|
||||
|
||||
var cate = await context.Categories
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
cate = cate.Where(x => x.Translations.Any(t => t.Info.Name.Contains(name, StringComparison.OrdinalIgnoreCase))).ToList();
|
||||
}
|
||||
|
||||
var lista = cate.Where(x => x.ParentCategoryId == null).ToList();
|
||||
Console.WriteLine($"{lista.Count}");
|
||||
|
||||
|
||||
foreach (var cat in lista)
|
||||
{
|
||||
cat.ChildCategories = NewMethod(cate, cat.Id);
|
||||
}
|
||||
|
||||
Console.WriteLine($"{lista.Count}");
|
||||
|
||||
return lista;
|
||||
|
||||
|
||||
|
||||
// if (!string.IsNullOrEmpty(name))
|
||||
// categories = categories.Where(x => x.Name.Contains(name));
|
||||
|
||||
// var lista = await categories.ToListAsync();
|
||||
// return lista;
|
||||
|
||||
}
|
||||
|
||||
private static List<Category> NewMethod(List<Category> categories, Guid parent)
|
||||
{
|
||||
var toreturn = new List<Category>();
|
||||
|
||||
var children = categories.Where(x => x.ParentCategoryId == parent).ToList();
|
||||
|
||||
foreach (var item in children)
|
||||
{
|
||||
item.ChildCategories = NewMethod(categories, item.Id);
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
public async Task<List<Category>> GetChildCategories(Guid categoryId)
|
||||
{
|
||||
var categories = new List<Category>();
|
||||
|
||||
categories = await context.Categories.Where(x => x.ParentCategoryId == categoryId).ToListAsync();
|
||||
|
||||
if (categories.Count != 0)
|
||||
{
|
||||
foreach (var category in categories)
|
||||
{
|
||||
categories.AddRange(await GetChildCategories(categoryId));
|
||||
}
|
||||
}
|
||||
|
||||
return categories;
|
||||
}
|
||||
|
||||
public async Task<List<Category>> GetChildrenList(Guid categoryId)
|
||||
{
|
||||
return await context.Categories.Where(x => x.Id == categoryId)
|
||||
.Include(x => x.ChildCategories)
|
||||
.SelectMany(x => x.ChildCategories)
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// public async Task<List<Category>> GetRandomCategories(int categoriesNeeded, int productsNeeded)
|
||||
// {
|
||||
// var count = await context.Categories.CountAsync();
|
||||
// var categories = new List<Category>();
|
||||
// var random = new Random();
|
||||
// var randoms = new List<int>();
|
||||
// for (int i = 0; i < categoriesNeeded; i++)
|
||||
// {
|
||||
// var newRandom = random.Next(count);
|
||||
// if (!randoms.Contains(newRandom))
|
||||
// {
|
||||
// randoms.Add(newRandom);
|
||||
// categories.Add(await context.Categories
|
||||
// .Skip(random.Next(count))
|
||||
// .Take(1)
|
||||
// .Include(x => x.Products)
|
||||
// .FirstOrDefaultAsync()
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// return categories;
|
||||
|
||||
// }
|
||||
|
||||
// public async Task<Category> GetCategoryAsync(int id)
|
||||
// {
|
||||
// return await context.Categories.FirstOrDefaultAsync(c => c.Id == id);
|
||||
// }
|
||||
|
||||
// public async Task<List<Category>> GetCategoriesPaginated(Pagination pagination)
|
||||
// {
|
||||
// var query = context.Categories.AsQueryable();
|
||||
// query = query.Skip((pagination.CurrentPage - 1) * pagination.PageSize)
|
||||
// .Take(pagination.PageSize);
|
||||
// return await query.ToListAsync();
|
||||
// }
|
||||
|
||||
// public async Task<List<CategoryVM>> GetRandomCategories(int count = 4)
|
||||
// {
|
||||
// return await context
|
||||
// .Categorys.OrderBy(x => Guid.NewGuid())
|
||||
// .Take(count)
|
||||
// .Select(x => Category.ToVM(x))
|
||||
// .ToListAsync();
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using Commerce.Contracts.DTOs;
|
||||
using Commerce.Domain;
|
||||
using Commerce.Domain.Entities;
|
||||
using Generic.Contracts.Generics;
|
||||
using Generic.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Commerce.Core.Services;
|
||||
|
||||
public class ProductService
|
||||
{
|
||||
private readonly Context context;
|
||||
|
||||
public ProductService(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public async Task CreateProduct(ProductVM productVM)
|
||||
{
|
||||
var product = Product.ToEntity(productVM);
|
||||
|
||||
if (productVM.ChildProducts?.Any() == true)
|
||||
{
|
||||
var childIds = productVM.ChildProducts.Select(x => x.Id).ToList();
|
||||
var existingChildren = await context.Products.Where(x => childIds.Contains(x.Id)).ToListAsync();
|
||||
product.ChildProducts = existingChildren;
|
||||
}
|
||||
|
||||
await context.Products.AddAsync(product);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task UpdateProduct(ProductVM productVM)
|
||||
{
|
||||
if (productVM.Id == null) throw new ArgumentException("Product ID is required for update.");
|
||||
|
||||
var existingProduct = await context.Products
|
||||
.Include(x => x.ChildProducts)
|
||||
.FirstOrDefaultAsync(x => x.Id == productVM.Id);
|
||||
|
||||
if (existingProduct == null) throw new KeyNotFoundException("Product not found.");
|
||||
|
||||
// Update properties
|
||||
existingProduct.Translations = productVM.Translations?.Select(t => new ProductTranslation
|
||||
{
|
||||
Language = t.Language,
|
||||
Info = new ProductInfo
|
||||
{
|
||||
Name = t.Info.Name,
|
||||
Description = t.Info.Description,
|
||||
TechnicalDetails = t.Info.TechnicalDetails?.Select(td => new Commerce.Domain.Entities.TechnicalDetail { Key = td.Key, Value = td.Value }).ToList() ?? new()
|
||||
}
|
||||
}).ToList() ?? new();
|
||||
|
||||
existingProduct.Photos = productVM.Photos ?? Array.Empty<string>();
|
||||
existingProduct.Price = productVM.Price ?? 0;
|
||||
existingProduct.Discount = productVM.Discount ?? 0;
|
||||
existingProduct.CodeName = productVM.CodeName ?? string.Empty;
|
||||
existingProduct.CategoryId = productVM.CategoryId ?? Guid.Empty;
|
||||
existingProduct.IsBundle = productVM.IsBundle;
|
||||
|
||||
// Update ChildProducts collection
|
||||
if (productVM.IsBundle)
|
||||
{
|
||||
var targetChildIds = productVM.ChildProducts?.Select(x => x.Id ?? Guid.Empty).ToList() ?? new List<Guid>();
|
||||
|
||||
// Remove items no longer in the list
|
||||
var itemsToRemove = existingProduct.ChildProducts.Where(x => !targetChildIds.Contains(x.Id)).ToList();
|
||||
foreach (var item in itemsToRemove) existingProduct.ChildProducts.Remove(item);
|
||||
|
||||
// Add new items
|
||||
var currentChildIds = existingProduct.ChildProducts.Select(x => x.Id).ToList();
|
||||
var idsToAdd = targetChildIds.Where(id => !currentChildIds.Contains(id)).ToList();
|
||||
|
||||
if (idsToAdd.Any())
|
||||
{
|
||||
var newChildren = await context.Products.Where(x => idsToAdd.Contains(x.Id)).ToListAsync();
|
||||
foreach (var child in newChildren) existingProduct.ChildProducts.Add(child);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
existingProduct.ChildProducts.Clear();
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task RemoveProduct(Guid id)
|
||||
{
|
||||
var product = await context.Products.FindAsync(id);
|
||||
if (product != null) context.Products.Remove(product);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<ProductVM> GetProduct(Guid id)
|
||||
{
|
||||
var product = await context.Products
|
||||
.Include(x => x.ChildProducts)
|
||||
.FirstOrDefaultAsync(x => x.Id == id);
|
||||
|
||||
return product != null ? Product.ToVM(product) : new ProductVM();
|
||||
}
|
||||
|
||||
public async Task<(List<ProductVM>, int)> FetchProduct(
|
||||
ProductFilter productFilter,
|
||||
Pagination pagination)
|
||||
{
|
||||
var query = context.Products
|
||||
.Include(x => x.ChildProducts)
|
||||
.AsQueryable();
|
||||
query = query.ApplyAdvancedFilter(productFilter);
|
||||
// query = query.ApplySorting(sortBy);
|
||||
if (productFilter.Random ?? false)
|
||||
{
|
||||
query = query.OrderBy(x => Guid.NewGuid());
|
||||
}
|
||||
else
|
||||
{
|
||||
// query = query.ApplySorting(sortBy);
|
||||
}
|
||||
var count = query.Count();
|
||||
query = query.Paginate(pagination);
|
||||
var lang = productFilter.Language;
|
||||
return (await query.Select(x => Product.ToVM(x, lang)).ToListAsync(), count);
|
||||
}
|
||||
|
||||
// public async Task<List<ProductVM>> GetRandomProducts(int count = 6)
|
||||
// {
|
||||
// return await context
|
||||
// .Products.OrderBy(x => Guid.NewGuid())
|
||||
// .Take(count)
|
||||
// .Select(x => Product.ToVM(x))
|
||||
// .ToListAsync();
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// using System;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Linq;
|
||||
// using System.Linq.Expressions;
|
||||
// using System.Reflection;
|
||||
// using System.Threading.Tasks;
|
||||
|
||||
// namespace Commerce.Core.Utility;
|
||||
|
||||
// public static class FilterExtension
|
||||
// {
|
||||
// public static IQueryable<T> ApplyFilter<T, TFilter>(this IQueryable<T> query, TFilter filter)
|
||||
// where TFilter : class
|
||||
// {
|
||||
// if (filter == null)
|
||||
// return query;
|
||||
|
||||
// var parameter = Expression.Parameter(typeof(T), "x");
|
||||
// Expression finalExpression = null;
|
||||
|
||||
// var filterProperties = typeof(TFilter)
|
||||
// .GetProperties()
|
||||
// .Where(p => p.GetValue(filter) != null);
|
||||
|
||||
// foreach (var filterProperty in filterProperties)
|
||||
// {
|
||||
// var filterValue = filterProperty.GetValue(filter);
|
||||
// if (filterValue == null)
|
||||
// continue;
|
||||
|
||||
// var propertyName = filterProperty.Name;
|
||||
// PropertyInfo entityProperty;
|
||||
|
||||
// Expression propertyExpression = null;
|
||||
// Expression comparison = null;
|
||||
|
||||
// // Handle special suffix cases
|
||||
// if (propertyName.EndsWith("_Start") || propertyName.EndsWith("_Min"))
|
||||
// {
|
||||
// entityProperty = typeof(T).GetProperty(
|
||||
// propertyName.Substring(0, propertyName.LastIndexOf('_'))
|
||||
// );
|
||||
// if (entityProperty != null)
|
||||
// {
|
||||
// propertyExpression = Expression.Property(parameter, entityProperty);
|
||||
// comparison = Expression.GreaterThanOrEqual(
|
||||
// propertyExpression,
|
||||
// Expression.Constant(filterValue, entityProperty.PropertyType)
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// else if (propertyName.EndsWith("_End") || propertyName.EndsWith("_Max"))
|
||||
// {
|
||||
// entityProperty = typeof(T).GetProperty(
|
||||
// propertyName.Substring(0, propertyName.LastIndexOf('_'))
|
||||
// );
|
||||
// if (entityProperty != null)
|
||||
// {
|
||||
// propertyExpression = Expression.Property(parameter, entityProperty);
|
||||
// comparison = Expression.LessThanOrEqual(
|
||||
// propertyExpression,
|
||||
// Expression.Constant(filterValue, entityProperty.PropertyType)
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// else if (propertyName.EndsWith("Name", StringComparison.OrdinalIgnoreCase))
|
||||
// {
|
||||
// entityProperty = typeof(T).GetProperty(propertyName);
|
||||
// if (entityProperty != null && entityProperty.PropertyType == typeof(string))
|
||||
// {
|
||||
// propertyExpression = Expression.Property(parameter, entityProperty);
|
||||
|
||||
// // For string Contains operation
|
||||
// var containsMethod = typeof(string).GetMethod(
|
||||
// "Contains",
|
||||
// new[] { typeof(string) }
|
||||
// );
|
||||
// var filterValueString = filterValue.ToString();
|
||||
|
||||
// comparison = Expression.Call(
|
||||
// propertyExpression,
|
||||
// containsMethod,
|
||||
// Expression.Constant(filterValueString, typeof(string))
|
||||
// );
|
||||
// }
|
||||
// else if (entityProperty != null)
|
||||
// {
|
||||
// // Fall back to equality comparison if it's not a string
|
||||
// propertyExpression = Expression.Property(parameter, entityProperty);
|
||||
// comparison = Expression.Equal(
|
||||
// propertyExpression,
|
||||
// Expression.Constant(filterValue, entityProperty.PropertyType)
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// entityProperty = typeof(T).GetProperty(propertyName);
|
||||
// if (entityProperty != null)
|
||||
// {
|
||||
// propertyExpression = Expression.Property(parameter, entityProperty);
|
||||
// comparison = Expression.Equal(
|
||||
// propertyExpression,
|
||||
// Expression.Constant(filterValue, entityProperty.PropertyType)
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (comparison != null)
|
||||
// {
|
||||
// finalExpression =
|
||||
// finalExpression == null
|
||||
// ? comparison
|
||||
// : Expression.AndAlso(finalExpression, comparison);
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (finalExpression != null)
|
||||
// {
|
||||
// var lambda = Expression.Lambda<Func<T, bool>>(finalExpression, parameter);
|
||||
// query = query.Where(lambda);
|
||||
// }
|
||||
|
||||
// return query;
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,27 @@
|
||||
// using System;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Linq;
|
||||
// using System.Threading.Tasks;
|
||||
|
||||
// namespace Commerce.Core.Utility;
|
||||
// public static class IEnumerableExtensions
|
||||
// {
|
||||
// public static IEnumerable<List<T>> Batch<T>(this IEnumerable<T> source, int batchSize)
|
||||
// {
|
||||
// var batch = new List<T>(batchSize);
|
||||
// foreach (var item in source)
|
||||
// {
|
||||
// batch.Add(item);
|
||||
// if (batch.Count == batchSize)
|
||||
// {
|
||||
// yield return batch;
|
||||
// batch = new List<T>(batchSize);
|
||||
// }
|
||||
// }
|
||||
// if (batch.Count > 0)
|
||||
// {
|
||||
// yield return batch;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
// using System;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Linq;
|
||||
// using System.Threading.Tasks;
|
||||
// using Contracts.DTOs;
|
||||
// using Contracts.DTOs.Generic;
|
||||
|
||||
// namespace Commerce.Core.Utility;
|
||||
// public static class Pagination<T>
|
||||
// where T : class
|
||||
// {
|
||||
// public static IQueryable<T> Paginate(IQueryable<T> query, Pagination pagination)
|
||||
// {
|
||||
// return query
|
||||
// .Skip((pagination.CurrentPage.Value - 1) * pagination.PageSize.Value)
|
||||
// .Take(pagination.PageSize.Value);
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// using System;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Linq;
|
||||
// using System.Threading.Tasks;
|
||||
// using Contracts.DTOs;
|
||||
// using Contracts.DTOs.Generic;
|
||||
|
||||
// namespace Commerce.Core.Utility;
|
||||
// public static class PaginationExtension
|
||||
// {
|
||||
// public static IQueryable<T> Paginate<T>(this IQueryable<T> query, Pagination pagination)
|
||||
// {
|
||||
// if (pagination.CurrentPage.HasValue && pagination.PageSize.HasValue)
|
||||
// return query
|
||||
// .Skip((pagination.CurrentPage.Value - 1) * pagination.PageSize.Value)
|
||||
// .Take(pagination.PageSize.Value);
|
||||
// else
|
||||
// return query;
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// using System;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Linq;
|
||||
// using System.Linq.Expressions;
|
||||
// using System.Threading.Tasks;
|
||||
// using Contracts.DTOs.Generic;
|
||||
|
||||
// namespace Commerce.Core.Utility;
|
||||
|
||||
// public static class QueryableExtensions
|
||||
// {
|
||||
// public static IQueryable<T> ApplySorting<T>(this IQueryable<T> source, SortModel sortBy)
|
||||
// {
|
||||
// // Parameter for lambda expression, e.g., "p" in "p => p.Property"
|
||||
// var parameter = Expression.Parameter(typeof(T), "p");
|
||||
|
||||
// // Access the property on the parameter, e.g., "p.Property"
|
||||
// var property = Expression.Property(parameter, sortBy.SortBy);
|
||||
|
||||
// // Cast property access to an object (boxing value types)
|
||||
// var converted = Expression.Convert(property, typeof(object));
|
||||
|
||||
// // Create the lambda expression, e.g., "p => (object)p.Property"
|
||||
// var keySelector = Expression.Lambda<Func<T, object>>(converted, parameter);
|
||||
|
||||
// // Apply OrderBy or OrderByDescending based on the ascending flag
|
||||
// return sortBy.SortDirection == SortDir.Ascending
|
||||
// ? source.OrderBy(keySelector)
|
||||
// : source.OrderByDescending(keySelector);
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,45 @@
|
||||
// using System;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Linq;
|
||||
// using System.Linq.Expressions;
|
||||
// using System.Reflection;
|
||||
// using System.Threading.Tasks;
|
||||
// using Contracts.DTOs.Generic;
|
||||
// using Microsoft.EntityFrameworkCore;
|
||||
|
||||
// namespace Commerce.Core.Utility;
|
||||
|
||||
// public static class SortExt
|
||||
// {
|
||||
// public static IQueryable<T> ApplySort<T>(this IQueryable<T> query, SortModel sortModel)
|
||||
// {
|
||||
// if (string.IsNullOrWhiteSpace(sortModel?.SortBy))
|
||||
// return query;
|
||||
|
||||
// // Get the property info
|
||||
// var propertyInfo = typeof(T).GetProperty(
|
||||
// sortModel.SortBy,
|
||||
// BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance
|
||||
// );
|
||||
|
||||
// if (propertyInfo == null)
|
||||
// throw new ArgumentException(
|
||||
// $"No property '{sortModel.SortBy}' on type '{typeof(T).Name}'"
|
||||
// );
|
||||
|
||||
// // Create x => x.PropertyName
|
||||
// var parameter = Expression.Parameter(typeof(T), "x");
|
||||
// var property = Expression.Property(parameter, propertyInfo);
|
||||
// var lambda = Expression.Lambda(property, parameter);
|
||||
|
||||
// // Call OrderBy or OrderByDescending dynamically
|
||||
// string methodName = sortModel.SortBy?.ToLower() == "desc" ? "OrderByDescending" : "OrderBy";
|
||||
// var result = typeof(Queryable)
|
||||
// .GetMethods()
|
||||
// .First(m => m.Name == methodName && m.GetParameters().Length == 2)
|
||||
// .MakeGenericMethod(typeof(T), propertyInfo.PropertyType)
|
||||
// .Invoke(null, new object[] { query, lambda });
|
||||
|
||||
// return (IQueryable<T>)result;
|
||||
// }
|
||||
// }
|
||||
Reference in New Issue
Block a user