Added Generics
This commit is contained in:
parent
7601a394b4
commit
8bca3f1f9d
@ -1,6 +1,7 @@
|
||||
using Core.Entities;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Core.Interfaces;
|
||||
using Core.Specifications;
|
||||
|
||||
namespace API.Controllers
|
||||
{
|
||||
@ -8,36 +9,42 @@ namespace API.Controllers
|
||||
[Route("api/[controller]")]
|
||||
public class ProductsController : ControllerBase
|
||||
{
|
||||
private readonly iProductRepository _repo;
|
||||
public ProductsController(iProductRepository repo)
|
||||
private readonly IGenericRepository<Product> _productsRepo;
|
||||
private readonly IGenericRepository<ProductBrand> _productBrandRepo;
|
||||
private readonly IGenericRepository<ProductType> _productTypeRepo;
|
||||
public ProductsController(IGenericRepository<Product> productsRepo, IGenericRepository<ProductBrand> productBrandRepo, IGenericRepository<ProductType> productTypeRepo)
|
||||
{
|
||||
_repo = repo;
|
||||
_productTypeRepo = productTypeRepo;
|
||||
_productBrandRepo = productBrandRepo;
|
||||
_productsRepo = productsRepo;
|
||||
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<List<Product>>> GetProducts()
|
||||
{
|
||||
var products = await _repo.GetProductsAync();
|
||||
|
||||
var spec = new ProductsWithTypesAndBrandsSpecification();
|
||||
var products = await _productsRepo.ListAsync(spec);
|
||||
return Ok(products);
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public async Task<ActionResult<Product>> GetProduct(int id)
|
||||
{
|
||||
return await _repo.GetProductByIdAsync(id);
|
||||
var spec = new ProductsWithTypesAndBrandsSpecification(id);
|
||||
return await _productsRepo.GetEntityWithSpec(spec);
|
||||
}
|
||||
|
||||
[HttpGet("brands")]
|
||||
public async Task<ActionResult<IReadOnlyList<ProductBrand>>> GetProductBrands()
|
||||
{
|
||||
return Ok(await _repo.GetProductBrandsAsync());
|
||||
return Ok(await _productBrandRepo.ListAllAsync());
|
||||
}
|
||||
|
||||
[HttpGet("types")]
|
||||
public async Task<ActionResult<IReadOnlyList<ProductType>>> GetProductTypes()
|
||||
{
|
||||
return Ok(await _repo.GetProductTypesAsync());
|
||||
return Ok(await _productTypeRepo.ListAllAsync());
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using Infrastructure;
|
||||
using Infrastructure.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@ -16,7 +17,7 @@ namespace API
|
||||
{
|
||||
var context = services.GetRequiredService<StoreContext>();
|
||||
await context.Database.MigrateAsync();
|
||||
await Infrastructure.StoreContextSeed.SeedAsync(context, loggerFactory);
|
||||
await StoreContextSeed.SeedAsync(context, loggerFactory);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -21,6 +21,7 @@ namespace API
|
||||
services.AddControllers();
|
||||
services.AddDbContext<StoreContext>(x => x.UseSqlite(_config.GetConnectionString("DefaultConnection")));
|
||||
services.AddScoped<iProductRepository, ProductRepository>();
|
||||
services.AddScoped(typeof(IGenericRepository<>), (typeof(GenericRepository<>)));
|
||||
services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebAPIv5", Version = "v1" });
|
||||
|
13
Core/Interfaces/IGenericRepository.cs
Normal file
13
Core/Interfaces/IGenericRepository.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using Core.Entities;
|
||||
using Core.Specifications;
|
||||
|
||||
namespace Core.Interfaces
|
||||
{
|
||||
public interface IGenericRepository<T> where T : BaseEntity
|
||||
{
|
||||
Task<T> GetByIdAsync(int id);
|
||||
Task<IReadOnlyList<T>> ListAllAsync();
|
||||
Task<T> GetEntityWithSpec(ISpecification<T> spec);
|
||||
Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec);
|
||||
}
|
||||
}
|
23
Core/Specifications/BaseSpecification.cs
Normal file
23
Core/Specifications/BaseSpecification.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Core.Specifications
|
||||
{
|
||||
public class BaseSpecification<T> : ISpecification<T>
|
||||
{
|
||||
public BaseSpecification()
|
||||
{
|
||||
}
|
||||
|
||||
public BaseSpecification(Expression<Func<T, bool>> criteria)
|
||||
{
|
||||
Criteria = criteria;
|
||||
}
|
||||
public Expression<Func<T, bool>> Criteria { get; }
|
||||
public List<Expression<Func<T, object>>> Includes { get; } =
|
||||
new List<Expression<Func<T, object>>>();
|
||||
protected void AddInclude(Expression<Func<T, object>> includeExpression)
|
||||
{
|
||||
Includes.Add(includeExpression);
|
||||
}
|
||||
}
|
||||
}
|
11
Core/Specifications/ISpecification.cs
Normal file
11
Core/Specifications/ISpecification.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Core.Specifications
|
||||
{
|
||||
public interface ISpecification<T>
|
||||
{
|
||||
Expression<Func<T, bool>> Criteria {get; }
|
||||
List<Expression<Func<T, object>>> Includes {get; }
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
using System.Linq.Expressions;
|
||||
using Core.Entities;
|
||||
|
||||
namespace Core.Specifications
|
||||
{
|
||||
public class ProductsWithTypesAndBrandsSpecification : BaseSpecification<Product>
|
||||
{
|
||||
public ProductsWithTypesAndBrandsSpecification()
|
||||
{
|
||||
AddInclude(x => x.ProductType);
|
||||
AddInclude(x => x.ProductBrand);
|
||||
}
|
||||
|
||||
public ProductsWithTypesAndBrandsSpecification(int id) : base(x => x.Id == id)
|
||||
{
|
||||
AddInclude(x => x.ProductType);
|
||||
AddInclude(x => x.ProductBrand);
|
||||
}
|
||||
}
|
||||
}
|
41
Infrastructure/Data/GenericRepository.cs
Normal file
41
Infrastructure/Data/GenericRepository.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using Core.Entities;
|
||||
using Core.Interfaces;
|
||||
using Core.Specifications;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Infrastructure.Data
|
||||
{
|
||||
public class GenericRepository<T> : IGenericRepository<T> where T : BaseEntity
|
||||
{
|
||||
private readonly StoreContext _context;
|
||||
public GenericRepository(StoreContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<T> GetByIdAsync(int id)
|
||||
{
|
||||
return await _context.Set<T>().FindAsync(id);
|
||||
}
|
||||
|
||||
|
||||
public async Task<IReadOnlyList<T>> ListAllAsync()
|
||||
{
|
||||
return await _context.Set<T>().ToListAsync();
|
||||
}
|
||||
public async Task<T> GetEntityWithSpec(ISpecification<T> spec)
|
||||
{
|
||||
return await ApplySpecification(spec).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<T>> ListAsync(ISpecification<T> spec)
|
||||
{
|
||||
return await ApplySpecification(spec).ToListAsync();
|
||||
}
|
||||
|
||||
private IQueryable<T> ApplySpecification(ISpecification<T> spec)
|
||||
{
|
||||
return SpecificationEvaluator<T>.GetQuery(_context.Set<T>().AsQueryable(), spec);
|
||||
}
|
||||
}
|
||||
}
|
23
Infrastructure/Data/SpecificationEvaluator.cs
Normal file
23
Infrastructure/Data/SpecificationEvaluator.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using Core.Entities;
|
||||
using Core.Specifications;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Infrastructure.Data
|
||||
{
|
||||
public class SpecificationEvaluator<TEntity> where TEntity : BaseEntity
|
||||
{
|
||||
public static IQueryable<TEntity> GetQuery(IQueryable<TEntity> inputQuery, ISpecification<TEntity> spec)
|
||||
{
|
||||
var query = inputQuery;
|
||||
|
||||
if (spec.Criteria != null)
|
||||
{
|
||||
query = query.Where(spec.Criteria);
|
||||
}
|
||||
|
||||
query = spec.Includes.Aggregate(query, (current, include) => current.Include(include));
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user