C# 将现有控制器操作转换为通用方法

C# 将现有控制器操作转换为通用方法,c#,asp.net-web-api,.net-5,C#,Asp.net Web Api,.net 5,在我的ASP.NET5WebAPI项目中,我发现我的许多核心控制器包含完全相同的CRUD方法。我发现我只是简单地复制/粘贴代码,搜索和替换主类型。警钟!这引发了这样的想法:如果可能的话,我想创建这些操作的通用实现,以减少类似的代码。这将有助于代码的可维护性等 有什么建议吗?下面是一个示例类,由VehicleType使用。我的其他类(组织、国家等)非常相似,都包含执行以下操作的方法:GetAll、Get、Create、Update和Delete [Authorize] [ApiController

在我的ASP.NET5WebAPI项目中,我发现我的许多核心控制器包含完全相同的CRUD方法。我发现我只是简单地复制/粘贴代码,搜索和替换主类型。警钟!这引发了这样的想法:如果可能的话,我想创建这些操作的通用实现,以减少类似的代码。这将有助于代码的可维护性等

有什么建议吗?下面是一个示例类,由VehicleType使用。我的其他类(组织、国家等)非常相似,都包含执行以下操作的方法:GetAll、Get、Create、Update和Delete

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class VehicleTypeController : Controller
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<VehicleTypeController> _logger;
    private readonly IMapper _mapper;

    public VehicleTypeController(IUnitOfWork unitOfWork, ILogger<VehicleTypeController> logger, IMapper mapper)
    {
        _unitOfWork = unitOfWork;
        _logger = logger;
        _mapper = mapper;
    }

    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> Get()
    {
        var countries = await _unitOfWork.VehicleTypes.GetAll();

        var results = _mapper.Map<IList<VehicleTypeDTO>>(countries);

        return Ok(results);
    }

    [HttpGet("{id:int}", Name = "Get")]    
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> Get(int id)
    {
        var VehicleType = await _unitOfWork.VehicleTypes.Get(i => i.Id == id);

        var results = _mapper.Map<VehicleTypeDTO>(VehicleType);

        return Ok(results);
    }

    [Authorize(Roles = "Administrator")]
    [HttpPost]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> Create([FromBody] CreateVehicleTypeDTO VehicleTypeDto)
    {
        if (!ModelState.IsValid)
        {
            _logger.LogError($"Invalid POST attempt in {nameof(CreateVehicleType)}");
            return BadRequest(ModelState);
        }

        var VehicleType = _mapper.Map<VehicleType>(VehicleTypeDto);
        await _unitOfWork.VehicleTypes.Insert(VehicleType);
        await _unitOfWork.Save();

        return CreatedAtRoute("Get", new { id = VehicleType.Id }, VehicleType);
    }

    [Authorize(Roles = "Administrator")]
    [HttpPut("{id:int}")]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> Update(int id, [FromBody] UpdateVehicleTypeDTO VehicleTypeDto)    
    {
        if (!ModelState.IsValid || id < 1)
        {
            _logger.LogError($"Invalid UPDATE attempt in {nameof(Update)}");
            return BadRequest(ModelState);
        }

        var VehicleType = await _unitOfWork.VehicleTypes.Get(a => a.Id == id);
        if (VehicleType == null)
        {
            _logger.LogError($"Submitted data is invalid.");
            return BadRequest(ModelState);
        }

        _mapper.Map(VehicleTypeDto, VehicleType);
        _unitOfWork.VehicleTypes.Update(VehicleType);
        await _unitOfWork.Save();

        return NoContent();
    }

    [Authorize(Roles = "Administrator")]
    [HttpDelete("{id:int}")]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> Delete(int id)
    {
        if (id < 1)
        {
            _logger.LogError($"Invalid DELETE attempt in {nameof(Delete)}");
            return BadRequest();
        }

        var VehicleType = _unitOfWork.VehicleTypes.Get(i => i.Id == id);
        if (VehicleType == null)
        {
            _logger.LogError($"Invalid DELETE attempt in {nameof(Delete)}");
            return BadRequest("Submitted data is invalid.");
        }

        await _unitOfWork.VehicleTypes.Delete(id);
        await _unitOfWork.Save();

        return NoContent();
    }
}
[授权]
[ApiController]
[路由(“api/[控制器]”)]
公共类车辆类型控制器:控制器
{
私人只读i工作单元(unitof工作单元);;
专用只读ILogger\u记录器;
专用只读IMapper\u映射器;
公共车辆类型控制器(IUnitOfWork、ILogger记录器、IMapper映射器)
{
_unitOfWork=unitOfWork;
_记录器=记录器;
_映射器=映射器;
}
[HttpGet]
[产品响应类型(StatusCodes.Status200OK)]
[产品响应类型(StatusCodes.Status500InternalServerError)]
公共异步任务Get()
{
var countries=wait_unitOfWork.VehicleTypes.GetAll();
var结果=_mapper.Map(国家);
返回Ok(结果);
}
[HttpGet(“{id:int}”,Name=“Get”)]
[产品响应类型(StatusCodes.Status200OK)]
[产品响应类型(StatusCodes.Status500InternalServerError)]
公共异步任务Get(int-id)
{
var VehicleType=await\u unitOfWork.VehicleTypes.Get(i=>i.Id==Id);
var结果=_mapper.Map(车辆类型);
返回Ok(结果);
}
[授权(角色=“管理员”)]
[HttpPost]
[产品响应类型(StatusCodes.Status400BadRequest)]
[产品响应类型(StatusCodes.Status201Created)]
[产品响应类型(StatusCodes.Status500InternalServerError)]
公共异步任务创建([FromBody]CreateVehicleTypeDTO VehicleTypeDto)
{
如果(!ModelState.IsValid)
{
_logger.LogError($“在{nameof(CreateVehicleType)}中的POST尝试无效”);
返回请求(ModelState);
}
var VehicleType=\u mapper.Map(VehicleTypeDto);
等待工作单元。车辆类型。插入(车辆类型);
wait_unitOfWork.Save();
返回CreatedAtRoute(“Get”,new{id=VehicleType.id},VehicleType);
}
[授权(角色=“管理员”)]
[HttpPut(“{id:int}”)]
[产品响应类型(StatusCodes.Status400BadRequest)]
[产品响应类型(StatusCodes.Status204NoContent)]
[产品响应类型(StatusCodes.Status500InternalServerError)]
公共异步任务更新(int id,[FromBody]UpdateHicleTypedTo VehicleTypeDto)
{
如果(!ModelState.IsValid | | id<1)
{
_logger.LogError($“在{nameof(UPDATE)}中的更新尝试无效”);
返回请求(ModelState);
}
var VehicleType=await\u unitOfWork.VehicleTypes.Get(a=>a.Id==Id);
如果(VehicleType==null)
{
_logger.LogError($“提交的数据无效”);
返回请求(ModelState);
}
_mapper.Map(车辆类型DTO,车辆类型);
_工作单元。车辆类型。更新(车辆类型);
wait_unitOfWork.Save();
返回NoContent();
}
[授权(角色=“管理员”)]
[HttpDelete(“{id:int}”)]
[产品响应类型(StatusCodes.Status400BadRequest)]
[产品响应类型(StatusCodes.Status204NoContent)]
[产品响应类型(StatusCodes.Status500InternalServerError)]
公共异步任务删除(int-id)
{
if(id<1)
{
_logger.LogError($“在{nameof(DELETE)}中的删除尝试无效”);
返回请求();
}
var VehicleType=\u unitOfWork.VehicleTypes.Get(i=>i.Id==Id);
如果(VehicleType==null)
{
_logger.LogError($“在{nameof(DELETE)}中的删除尝试无效”);
返回请求(“提交的数据无效”);
}
等待(u unitOfWork.VehicleTypes.Delete)(id);;
wait_unitOfWork.Save();
返回NoContent();
}
}
使用这些方法创建接口的最佳方法是让这些类实现该接口吗?例如像这样的事情

public interface IGenericCRUD
{
    Task<IActionResult> Get();
    Task<IActionResult> Get(int id);
    Task<IActionResult> Create([FromBody] object myDto);
    Task<IActionResult> Update(int id, [FromBody] object myDto);
    Task<IActionResult> Delete(int id);
}
公共接口IGenericCRUD
{
任务Get();
任务获取(int-id);
任务创建([FromBody]对象myDto);
任务更新(int-id,[FromBody]对象myDto);
任务删除(int-id);
}
然后使用反射根据泛型类型动态调用适当的方法

因此,创建一个实现IGenericCRUD并包含核心CRUD代码的泛型CRUD类,但使用泛型T

public class GenericCrud<T, TEntityDto> 
公共类泛型CRUD
然后,在Get方法中,例如,类似这样的东西?(它无法编译,因此我不确定是否接近。)

公共异步任务Get() { var getAllResults=await_unitOfWork.GetType(T).GetAll(); var results=\u mapper.Map(getAllResults); 返回结果; } 我走对了吗?有没有办法发布这个类的“通用”版本,让我看看你的方法


谢谢

正如我们在评论中所讨论的,您可以尝试这样做:

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class CRUDControllerBase<T, TDto, TCreate, TUpdate> : Controller
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<CRUDControllerBase<T,TDto, TCreate, TUpdate>> _logger;
    private readonly IMapper _mapper;

    public VehicleTypeController(IUnitOfWork unitOfWork, ILogger<CRUDControllerBase<T, TDto, TCreate, TUpdate>> logger, IMapper mapper)
    {
        _unitOfWork = unitOfWork;
        _logger = logger;
        _mapper = mapper;
    }

    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IList<TDto>> Get()
    {
        // if you have used simple EF db context you could use here 
        // .Set<T>().ToListAsync() here  
        var countries = await _unitOfWork.XXX.GetAll();

        var results = _mapper.Map<IList<TDto>>(countries);

        return results;
    }
[授权]
[ApiController]
[路由(“api/[控制器]”)]
公共类CRUDControllerBase:控制器
{
私人只读i工作单元(unitof工作单元);;
专用只读ILogger\u记录器;
专用只读IMapper\u映射器;
公共车辆类型控制器(IUnitOfWork、ILogger记录器、IMapper映射器)
{
_unitOfWork=unitOfWork;
_记录器=记录器;
_映射器=映射器;
}
[HttpGet]
[产品响应类型(StatusCodes.Status200OK)]
[Pr
[Authorize]
[ApiController]
[Route("api/[controller]")]
public class CRUDControllerBase<T, TDto, TCreate, TUpdate> : Controller
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger<CRUDControllerBase<T,TDto, TCreate, TUpdate>> _logger;
    private readonly IMapper _mapper;

    public VehicleTypeController(IUnitOfWork unitOfWork, ILogger<CRUDControllerBase<T, TDto, TCreate, TUpdate>> logger, IMapper mapper)
    {
        _unitOfWork = unitOfWork;
        _logger = logger;
        _mapper = mapper;
    }

    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IList<TDto>> Get()
    {
        // if you have used simple EF db context you could use here 
        // .Set<T>().ToListAsync() here  
        var countries = await _unitOfWork.XXX.GetAll();

        var results = _mapper.Map<IList<TDto>>(countries);

        return results;
    }