Я не совсем уверен, что вы ищете, но с точки зрения API, я бы использовал абстрактный контроллер продукта, а затем вывел бы контроллер для каждого конкретного типа продукта из этого:
[Route("api/[controller]")]
[ApiController]
public abstract class ProductController<TProduct, TProductDTO> : ControllerBase
where TProduct : Product, new()
where TProductDTO : class, new()
{
}
public class DownloadableController : ProductController<Downloadable, DownloadableDTO>
{
}
public class ShippableController : ProductController<Shippable, ShippableDTO>
{
}
Затем вы строите все конечные точки на своем абстрактном контроллере продукта, используя универсальные типы TProduct
и TProductDTO
.Например, у вас может быть что-то вроде:
[HttpPost("")]
public async Task<ActionResult<TProductResource>> Create(TProductDTO dto)
{
var product = _mapper.Map<TProduct>(dto);
_context.Add(product);
await _context.SaveChangesAsync();
return CreatedAt("Get", new { product.Id }, _mapper.Map<TProductDTO>(product));
}
Из-за универсальных типов этот же метод работает для всех производных контроллеров, без необходимости переопределения или даже переопределения, хотя вы можете разрешить его переопределить с помощьюдобавив ключевое слово virtual
.Как правило, лучше добавлять методы-заполнители.Например, вы можете сделать что-то вроде:
private virtual Task BeforeCreateAsync(TProduct product, TProductDTO dto) =>
Task.CompletedTask;
private virtual Task AfterCreateAsync(TProduct product, TProductDTO dto) =>
Task.CompletedTask;
И затем оберните свой вызов SaveChangesAsync
:
_context.Add(product);
await BeforeCreateAsync(product, dto);
await _context.SaveChangesAsync();
await AfterCreateAsync(product, dto);
Затем, в ваших производных контроллерах, вы можете переопределить их для заглушки с дополнительными функциями:
private override async Task BeforeCreateAsync(Downloadable product, DownloadableDTO dto)
{
// do something specific to downloadable products
}
Таким образом, большая часть вашей логики остается автономной,Вы можете добавить столько методов-заполнителей, сколько имеет смысл для вашего приложения.