问题描述
我有一个基本控制器,它应该返回一个对象列表(并将它们从 DTO 映射到业务)
如果子控制器决定应用规范(过滤或包含某些内容),它可以通过覆盖 GetSpecification()
方法来实现。
但默认情况下,在基类中我不想过滤对象。
[Route("api/[controller]")]
[ApiController]
public class BaseApiController<TBusinessModel,TApiModel,TBaseRepository> : BaseController<TBaseRepository>
where TBusinessModel : BaseEntity
where TBaseRepository : IBaseRepository
{
public BaseApiController(TBaseRepository repository,IMapper mapper) : base(repository,mapper)
{ }
// GET: api/Bars
[HttpGet]
public virtual async Task<IActionResult> List()
{
var spec = GetSpecification();
var items = await _repository.ListAsync<TBusinessModel>(spec);
var apiItems = _mapper.Map<List<TApiModel>>(items);
return Ok(apiItems);
}
protected virtual ISpecification<TBusinessModel> GetSpecification()
{
// how to get an empty specification that does not filter or do something?
return new Specification<TBusinessModel>();
}
}
我使用 ardalis specifications,但它可以是任何通用的 IQueryable
东西...
实际上它说:
错误 CS0144 无法创建抽象类型的实例或 接口'规格'
解决方法
错误信息就够了,你不能实例化接口或抽象类。那是因为它没有任何逻辑。详情可以参考这个document。
如果你想创建一个新的 Specification 类,我建议你可以尝试使用 SpecificationBuilder
类。
关于如何使用它的更多细节,你可以参考这个github link.
,具有空规范是完全有效的构造。一旦评估将返回所有记录。在下面的例子中,它将返回所有客户
public class CustomerSpec : Specification<Customer>
{
public CustomerSpec()
{
}
}
但是,这里的问题不是空规范。您正在尝试添加另一层抽象,并尝试直接实例化 Specification<T>
。 Specification
是一个抽象类,因此您将无法创建实例。如果您渴望实现该基础架构,只需添加您自己从 Specification<T>
继承的基类,然后将其用作应用中所有其他规范的基础。
注意:我们使类抽象,正是为了阻止用户这样做:) 但是,请确保您可以继续以这种方式使用它。
public class AppSpecification<T> : Specification<T>
{
}
,
最后,由于提供的库中不存在像空规范这样的东西,我自己创建了它:
public class EmptySpecification<T> : Specification<T>
{
public EmptySpecification()
{
// does nothing
}
}
然后在 BaseController 中使用(最后几行):
[Route("api/[controller]")]
[ApiController]
public class BaseApiController<TBusinessModel,TDto,TBaseRepository> : BaseController<TBusinessModel,TBaseRepository>
where TBusinessModel : BaseEntity
where TBaseRepository : IBaseRepository
{
public BaseApiController(TBaseRepository repository,IMapper mapper) : base(repository,mapper) { }
[HttpGet]
public virtual async Task<IActionResult> List()
{
var spec = ListSpecification();
var items = await _repository.ListAsync<TBusinessModel>(spec);
var apiItems = ToDto(items);
return Ok(apiItems);
}
protected virtual ISpecification<TBusinessModel> ListSpecification()
{
return new EmptySpecification<TBusinessModel>();
}
}