Skip to content

Commit

Permalink
feat: Adding Key Generic Type
Browse files Browse the repository at this point in the history
  • Loading branch information
Edgar Mesquita authored and Edgar Mesquita committed Sep 4, 2023
1 parent 373a683 commit 5c7de38
Show file tree
Hide file tree
Showing 15 changed files with 156 additions and 108 deletions.
15 changes: 8 additions & 7 deletions src/eQuantic.Core.Api.Crud/Controllers/CrudControllerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ namespace eQuantic.Core.Api.Crud.Controllers;
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TRequest"></typeparam>
public abstract class CrudControllerBase<TEntity, TRequest> : ControllerBase, ICrudController<TEntity, TRequest> where TEntity : class, new()
/// <typeparam name="TKey"></typeparam>
public abstract class CrudControllerBase<TEntity, TRequest, TKey> : ControllerBase, ICrudController<TEntity, TRequest, TKey> where TEntity : class, new()
{
private readonly ICrudService<TEntity, TRequest> _service;
private readonly ICrudService<TEntity, TRequest, TKey> _service;

/// <summary>
/// Initializes a new instance of the <see cref="CrudControllerBase{TEntity, TRequest}"/> class
/// Initializes a new instance of the <see cref="CrudControllerBase{TEntity, TRequest, TKey}"/> class
/// </summary>
/// <param name="service"></param>
protected CrudControllerBase(ICrudService<TEntity, TRequest> service)
protected CrudControllerBase(ICrudService<TEntity, TRequest, TKey> service)
{
_service = service;
}
Expand All @@ -44,7 +45,7 @@ public virtual async Task<IActionResult> GetPagedList([FromQuery] PagedListReque
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("{id:int}")]
public virtual async Task<IActionResult> GetById([FromRoute] ItemRequest request, CancellationToken cancellationToken = default)
public virtual async Task<IActionResult> GetById([FromRoute] ItemRequest<TKey> request, CancellationToken cancellationToken = default)
{
var item = await _service.GetByIdAsync(request, cancellationToken);
return Ok(item);
Expand Down Expand Up @@ -80,7 +81,7 @@ public virtual async Task<IActionResult> Create([FromQuery] CreateRequest<TReque
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPut("{id:int}")]
public virtual async Task<IActionResult> Update([FromQuery] UpdateRequest<TRequest> request, CancellationToken cancellationToken = default)
public virtual async Task<IActionResult> Update([FromQuery] UpdateRequest<TRequest, TKey> request, CancellationToken cancellationToken = default)
{
var result = await _service.UpdateAsync(request, cancellationToken);
return NoContent();
Expand All @@ -93,7 +94,7 @@ public virtual async Task<IActionResult> Update([FromQuery] UpdateRequest<TReque
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpDelete("{id:int}")]
public virtual async Task<IActionResult> Delete([FromQuery] ItemRequest request, CancellationToken cancellationToken = default)
public virtual async Task<IActionResult> Delete([FromQuery] ItemRequest<TKey> request, CancellationToken cancellationToken = default)
{
var result = await _service.DeleteAsync(request, cancellationToken);
return NoContent();
Expand Down
9 changes: 5 additions & 4 deletions src/eQuantic.Core.Api.Crud/Controllers/ICrudController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ namespace eQuantic.Core.Api.Crud.Controllers;
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TRequest"></typeparam>
public interface ICrudController<TEntity, TRequest> where TEntity : class, new()
/// <typeparam name="TKey"></typeparam>
public interface ICrudController<TEntity, TRequest, TKey> where TEntity : class, new()
{
/// <summary>
/// Get entity by identifier
/// </summary>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IActionResult> GetById(ItemRequest request, CancellationToken cancellationToken = default);
Task<IActionResult> GetById(ItemRequest<TKey> request, CancellationToken cancellationToken = default);

/// <summary>
/// Get paged list of entity
Expand All @@ -41,7 +42,7 @@ Task<IActionResult> Create([FromQuery] CreateRequest<TRequest> request,
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IActionResult> Update([FromQuery] UpdateRequest<TRequest> request,
Task<IActionResult> Update([FromQuery] UpdateRequest<TRequest, TKey> request,
CancellationToken cancellationToken = default);

/// <summary>
Expand All @@ -50,5 +51,5 @@ Task<IActionResult> Update([FromQuery] UpdateRequest<TRequest> request,
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IActionResult> Delete([FromQuery] ItemRequest request, CancellationToken cancellationToken = default);
Task<IActionResult> Delete([FromQuery] ItemRequest<TKey> request, CancellationToken cancellationToken = default);
}
64 changes: 35 additions & 29 deletions src/eQuantic.Core.Api.Crud/Extensions/WepApplicationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,24 @@ public static WebApplication MapAllCrud(this WebApplication app, Action<AllCrudO
/// <param name="options">The options</param>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TService"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <returns></returns>
public static WebApplication MapReaders<TEntity, TService>(this WebApplication app,
public static WebApplication MapReaders<TEntity, TService, TKey>(this WebApplication app,
Action<CrudOptions<TEntity>>? options = null)
where TEntity : class, new()
where TService : IReaderService<TEntity>
where TService : IReaderService<TEntity, TKey>
{
var crudOptions = new CrudOptions<TEntity>();
options?.Invoke(crudOptions);

if ((crudOptions.Verbs & CrudEndpointVerbs.OnlyGetById) == CrudEndpointVerbs.OnlyGetById)
{
app.MapGetById<TEntity, TService>(crudOptions);
app.MapGetById<TEntity, TService, TKey>(crudOptions);
}

if ((crudOptions.Verbs & CrudEndpointVerbs.OnlyGetPaged) == CrudEndpointVerbs.OnlyGetPaged)
{
app.MapGetPagedList<TEntity, TService>(crudOptions);
app.MapGetPagedList<TEntity, TService, TKey>(crudOptions);
}

return app;
Expand All @@ -106,30 +107,31 @@ public static WebApplication MapReaders<TEntity, TService>(this WebApplication a
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TRequest"></typeparam>
/// <typeparam name="TService"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <returns></returns>
public static WebApplication MapCrud<TEntity, TRequest, TService>(this WebApplication app,
public static WebApplication MapCrud<TEntity, TRequest, TService, TKey>(this WebApplication app,
Action<CrudOptions<TEntity>>? options = null)
where TEntity : class, new()
where TService : ICrudService<TEntity, TRequest>
where TService : ICrudService<TEntity, TRequest, TKey>
{
var crudOptions = new CrudOptions<TEntity>();
options?.Invoke(crudOptions);

app.MapReaders<TEntity, TService>(options);
app.MapReaders<TEntity, TService, TKey>(options);

if ((crudOptions.Verbs & CrudEndpointVerbs.OnlyCreate) == CrudEndpointVerbs.OnlyCreate)
{
app.MapCreate<TEntity, TRequest, TService>(crudOptions);
app.MapCreate<TEntity, TRequest, TService, TKey>(crudOptions);
}

if ((crudOptions.Verbs & CrudEndpointVerbs.OnlyUpdate) == CrudEndpointVerbs.OnlyUpdate)
{
app.MapUpdate<TEntity, TRequest, TService>(crudOptions);
app.MapUpdate<TEntity, TRequest, TService, TKey>(crudOptions);
}

if ((crudOptions.Verbs & CrudEndpointVerbs.OnlyDelete) == CrudEndpointVerbs.OnlyDelete)
{
app.MapDelete<TEntity, TRequest, TService>(crudOptions);
app.MapDelete<TEntity, TRequest, TService, TKey>(crudOptions);
}

return app;
Expand All @@ -139,14 +141,14 @@ public static WebApplication MapCrud<TEntity, TRequest, TService>(this WebApplic
{
return interfaces
.FirstOrDefault(o =>
o.GenericTypeArguments.Length > 0 && o.GetGenericTypeDefinition() == typeof(ICrudService<,>));
o.GenericTypeArguments.Length > 0 && o.GetGenericTypeDefinition() == typeof(ICrudService<,,>));
}

private static Type? GetReaderServiceInterface(IEnumerable<Type> interfaces)
{
return interfaces
.FirstOrDefault(o =>
o.GenericTypeArguments.Length > 0 && o.GetGenericTypeDefinition() == typeof(IReaderService<>));
o.GenericTypeArguments.Length > 0 && o.GetGenericTypeDefinition() == typeof(IReaderService<,>));
}

private static Action<ICrudOptions>? GetCrudOptions(AllCrudOptions allCrudOptions, Type entityType)
Expand All @@ -161,9 +163,11 @@ private static void InvokeMapCrud(WebApplication app, Type crudInterface, AllCru
{
var entityType = crudInterface.GenericTypeArguments[0];
var requestType = crudInterface.GenericTypeArguments[1];
var keyType = crudInterface.GenericTypeArguments[2];

var crudOptions = GetCrudOptions(allCrudOptions, entityType);
var method = extensionType.GetMethod(nameof(MapCrud))
?.MakeGenericMethod(entityType, requestType, serviceType);
?.MakeGenericMethod(entityType, requestType, serviceType, keyType);

InvokeMethod(app, crudEndpoints, method, allCrudOptions, crudOptions);
}
Expand All @@ -172,9 +176,11 @@ private static void InvokeMapReaders(WebApplication app, Type crudInterface, All
Type extensionType, Type serviceType, MapCrudEndpointsAttribute crudEndpoints)
{
var entityType = crudInterface.GenericTypeArguments[0];
var keyType = crudInterface.GenericTypeArguments[1];

var crudOptions = GetCrudOptions(allCrudOptions, entityType);
var method = extensionType.GetMethod(nameof(MapReaders))
?.MakeGenericMethod(entityType, serviceType);
?.MakeGenericMethod(entityType, serviceType, keyType);

InvokeMethod(app, crudEndpoints, method, allCrudOptions, crudOptions);
}
Expand Down Expand Up @@ -219,13 +225,13 @@ private static string GetPattern<TEntity>(bool withId = false, Type? referenceTy
return pattern;
}

private static WebApplication MapGetById<TEntity, TService>(this WebApplication app,
private static WebApplication MapGetById<TEntity, TService, TKey>(this WebApplication app,
CrudOptions<TEntity> options)
where TEntity : class, new()
where TService : IReaderService<TEntity>
where TService : IReaderService<TEntity, TKey>
{
var pattern = GetPattern<TEntity>(true, options.Get.ReferenceType);
var handlers = new ReaderEndpointHandlers<TEntity, TService>(options);
var handlers = new ReaderEndpointHandlers<TEntity, TService, TKey>(options);
Delegate handler = options.Get.ReferenceType != null
? handlers.GetReferencedById
: handlers.GetById;
Expand All @@ -238,13 +244,13 @@ private static WebApplication MapGetById<TEntity, TService>(this WebApplication
return app;
}

private static WebApplication MapGetPagedList<TEntity, TService>(this WebApplication app,
private static WebApplication MapGetPagedList<TEntity, TService, TKey>(this WebApplication app,
CrudOptions<TEntity> options)
where TEntity : class, new()
where TService : IReaderService<TEntity>
where TService : IReaderService<TEntity, TKey>
{
var pattern = GetPattern<TEntity>(false, options.List.ReferenceType);
var handlers = new ReaderEndpointHandlers<TEntity, TService>(options);
var handlers = new ReaderEndpointHandlers<TEntity, TService, TKey>(options);
Delegate handler = options.List.ReferenceType != null
? handlers.GetReferencedPagedList
: handlers.GetPagedList;
Expand All @@ -256,13 +262,13 @@ private static WebApplication MapGetPagedList<TEntity, TService>(this WebApplica
return app;
}

private static WebApplication MapCreate<TEntity, TRequest, TService>(this WebApplication app,
private static WebApplication MapCreate<TEntity, TRequest, TService, TKey>(this WebApplication app,
CrudOptions<TEntity> options)
where TEntity : class, new()
where TService : ICrudService<TEntity, TRequest>
where TService : ICrudService<TEntity, TRequest, TKey>
{
var pattern = GetPattern<TEntity>(false, options.Create.ReferenceType);
var handlers = new CrudEndpointHandlers<TEntity, TRequest, TService>(options);
var handlers = new CrudEndpointHandlers<TEntity, TRequest, TService, TKey>(options);
Delegate handler = options.Create.ReferenceType != null
? handlers.ReferencedCreate
: handlers.Create;
Expand All @@ -273,13 +279,13 @@ private static WebApplication MapCreate<TEntity, TRequest, TService>(this WebApp
return app;
}

private static WebApplication MapUpdate<TEntity, TRequest, TService>(this WebApplication app,
private static WebApplication MapUpdate<TEntity, TRequest, TService, TKey>(this WebApplication app,
CrudOptions<TEntity> options)
where TEntity : class, new()
where TService : ICrudService<TEntity, TRequest>
where TService : ICrudService<TEntity, TRequest, TKey>
{
var pattern = GetPattern<TEntity>(true, options.Update.ReferenceType);
var handlers = new CrudEndpointHandlers<TEntity, TRequest, TService>(options);
var handlers = new CrudEndpointHandlers<TEntity, TRequest, TService, TKey>(options);
Delegate handler = options.Update.ReferenceType != null
? handlers.ReferencedUpdate
: handlers.Update;
Expand All @@ -291,13 +297,13 @@ private static WebApplication MapUpdate<TEntity, TRequest, TService>(this WebApp
return app;
}

private static WebApplication MapDelete<TEntity, TRequest, TService>(this WebApplication app,
private static WebApplication MapDelete<TEntity, TRequest, TService, TKey>(this WebApplication app,
CrudOptions<TEntity> options)
where TEntity : class, new()
where TService : ICrudService<TEntity, TRequest>
where TService : ICrudService<TEntity, TRequest, TKey>
{
var pattern = GetPattern<TEntity>(true, options.Delete.ReferenceType);
var handlers = new CrudEndpointHandlers<TEntity, TRequest, TService>(options);
var handlers = new CrudEndpointHandlers<TEntity, TRequest, TService, TKey>(options);
Delegate handler = options.Delete.ReferenceType != null
? handlers.ReferencedDelete
: handlers.Delete;
Expand Down
31 changes: 16 additions & 15 deletions src/eQuantic.Core.Api.Crud/Handlers/CrudEndpointHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ namespace eQuantic.Core.Api.Crud.Handlers;
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TRequest"></typeparam>
/// <typeparam name="TService"></typeparam>
internal sealed class CrudEndpointHandlers<TEntity, TRequest, TService>
/// <typeparam name="TKey"></typeparam>
internal sealed class CrudEndpointHandlers<TEntity, TRequest, TService, TKey>
where TEntity : class, new()
where TService : ICrudService<TEntity, TRequest>
where TService : ICrudService<TEntity, TRequest, TKey>
{
private readonly CrudOptions<TEntity> _options;

Expand All @@ -34,7 +35,7 @@ public CrudEndpointHandlers(CrudOptions<TEntity> options)
/// <param name="request"></param>
/// <param name="service"></param>
/// <returns></returns>
public async Task<CreatedAtRoute<int>> Create(
public async Task<CreatedAtRoute<TKey>> Create(
[FromBody] TRequest request,
[FromServices]TService service)
{
Expand All @@ -49,7 +50,7 @@ public async Task<CreatedAtRoute<int>> Create(
/// <param name="request"></param>
/// <param name="service"></param>
/// <returns></returns>
public async Task<CreatedAtRoute<int>> ReferencedCreate(
public async Task<CreatedAtRoute<TKey>> ReferencedCreate(
[FromRoute] int referenceId,
[FromBody] TRequest request,
[FromServices]TService service)
Expand All @@ -66,11 +67,11 @@ public async Task<CreatedAtRoute<int>> ReferencedCreate(
/// <param name="service"></param>
/// <returns></returns>
public async Task<Results<Ok, BadRequest>> Update(
[FromRoute] int id,
[FromRoute] TKey id,
[FromBody] TRequest request,
[FromServices]TService service)
{
var updateRequest = new UpdateRequest<TRequest>(id, request);
var updateRequest = new UpdateRequest<TRequest, TKey>(id, request);
return await Update(updateRequest, service);
}

Expand All @@ -84,11 +85,11 @@ public async Task<Results<Ok, BadRequest>> Update(
/// <returns></returns>
public async Task<Results<Ok, BadRequest>> ReferencedUpdate(
[FromRoute] int referenceId,
[FromRoute] int id,
[FromRoute] TKey id,
[FromBody] TRequest request,
[FromServices] TService service)
{
var updateRequest = new UpdateRequest<TRequest, int>(referenceId, id, request);
var updateRequest = new UpdateRequest<TRequest, TKey, int>(referenceId, id, request);
return await Update(updateRequest, service);
}

Expand All @@ -99,10 +100,10 @@ public async Task<Results<Ok, BadRequest>> ReferencedUpdate(
/// <param name="service"></param>
/// <returns></returns>
public async Task<Results<Ok, BadRequest>> Delete(
[FromRoute] int id,
[FromRoute] TKey id,
[FromServices]TService service)
{
var request = new ItemRequest(id);
var request = new ItemRequest<TKey>(id);
return await Delete(request, service);
}

Expand All @@ -115,14 +116,14 @@ public async Task<Results<Ok, BadRequest>> Delete(
/// <returns></returns>
public async Task<Results<Ok, BadRequest>> ReferencedDelete(
[FromRoute] int referenceId,
[FromRoute] int id,
[FromRoute] TKey id,
[FromServices] TService service)
{
var request = new ItemRequest<int>(referenceId, id);
var request = new ItemRequest<TKey, int>(referenceId, id);
return await Delete(request, service);
}

private async Task<CreatedAtRoute<int>> Create(
private async Task<CreatedAtRoute<TKey>> Create(
CreateRequest<TRequest> request,
TService service)
{
Expand All @@ -134,15 +135,15 @@ private async Task<CreatedAtRoute<int>> Create(
}

private static async Task<Results<Ok, BadRequest>> Update(
UpdateRequest<TRequest> request,
UpdateRequest<TRequest, TKey> request,
TService service)
{
var result = await service.UpdateAsync(request);
return result ? TypedResults.Ok() : TypedResults.BadRequest();
}

private static async Task<Results<Ok, BadRequest>> Delete(
ItemRequest request,
ItemRequest<TKey> request,
TService service)
{
var result = await service.DeleteAsync(request);
Expand Down
Loading

0 comments on commit 5c7de38

Please sign in to comment.