具有可选泛型参数的泛型和可覆盖控制器方法

时间:2019-11-17 22:03:11

标签: c# asp.net-core

我有以下通用控制器:

public abstract class ControllerBase<TEntity, TEntityDto>
{
    public async Task<ActionResult<IEnumerable<TEntityDto>>> GetAll()
    {
        ...
    }
}

我需要能够根据查询参数在与通用控制器(返回 all 实体)相同的路由上过滤实体。因此,我的想法是重写通用控制器并将其重写为:

public abstract class ControllerBase<TEntity, TEntityDto, TQueryParams>
{
    [HttpGet]
    [ProducesResponseType(200)]
    public async Task<ActionResult<IEnumerable<TEntityDto>>> GetAll(TQueryParams? queryParams)
    {
        // Notice the service layer method is called without parameters in the generic controller
        var instances = await _service.GetAll();

        return Ok(instances);
    }
}
public class DogsController : EntityControllerBase<Dog,DogDto>
{
    [HttpGet]
    [ProducesResponseType(200)]
    public async Task<ActionResult<IEnumerable<DogDto>>> GetAll(DogQueryParams queryParams)
        {
            var instances = await _service.ListDogs(queryParams.kennel, queryParams.birthYear);
            return Ok(instances);
        }
}

但是,我得到了错误:Only non-nullable value type could be underlying of 'System.Nullable'

我使用正确的方法吗?

实现所需行为的正确方法是什么? (当我需要根据可选查询参数过滤输出时,可以覆盖基本控制器方法GetAll

1 个答案:

答案 0 :(得分:0)

编译器错误告诉您“只能标记为可为空,尚未标记为可为空”。

引用类型固有地可以为空。实际上,只有在C#8.0中,我们才支持不可为空引用类型。使用编译器开关时,将其作为默认值会出现问题。

反过来,

结构本质上是不可为空的。可空语法最初是为他们发明的。使用C#8.0,它将是afaik的第一个扩展。

由于您没有通过where子句限制TQueryParams,所以编译器只能假定适用于结构的事物。对于泛型,它始终使用“最小公分母”。

但是请注意,即使使用C#8.0对非空引用类型的支持,据我所知MSIL实现也是如此,您不能互换使用它们。您仍然必须决定使用class还是struct,以使用可为空的语法。