我有以下通用控制器:
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
。
答案 0 :(得分:0)
编译器错误告诉您“只能标记为可为空,尚未标记为可为空”。
引用类型固有地可以为空。实际上,只有在C#8.0中,我们才支持不可为空引用类型。使用编译器开关时,将其作为默认值会出现问题。
反过来,结构本质上是不可为空的。可空语法最初是为他们发明的。使用C#8.0,它将是afaik的第一个扩展。
由于您没有通过where子句限制TQueryParams
,所以编译器只能假定适用于结构和的事物。对于泛型,它始终使用“最小公分母”。
但是请注意,即使使用C#8.0对非空引用类型的支持,据我所知MSIL实现也是如此,您不能互换使用它们。您仍然必须决定使用class还是struct,以使用可为空的语法。