我正在使用动作过滤器中的依赖项注入来验证数据库中是否存在针对我的API调用的实体。
异步操作过滤器在操作之前执行以验证实体是否存在,如果不存在,则返回404 not found http状态代码。由于EF已经在跟踪该实体,因此在执行操作之前进行此检查没有任何开销。
问题是我有通用服务和通用操作过滤器。我当然可以使用ServiceFilter
来获取通用过滤器的实例,但是我想创建自己的自定义过滤器。问题是我不知道如何在我的IFilterFactory实现中解析通用过滤器。
public class EntityExistsFilterFactory : Attribute, IFilterFactory
{
private readonly Type _type;
public bool IsReusable => false;
public EntityExistsFilterFactory(Type type)
{
_type = type;
}
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
var filter = serviceProvider.GetService(_type); //problem here as this returns an object
return filter;
}
}
如果我尝试通过过滤器工厂构造函数解析类型,则只会得到一个通用对象。现在,除非我对服务的类型参数进行硬编码(例如serviceProvider.GetService<IExampleService<Entity>>();
),否则无法获得特定实例。但是我希望这是通用的,因此我可以简单地在属性中传递所需的类型
例如很像:[ServiceFilter(typeof(IExampleService<Entity>))]
我想要一个自定义过滤器,因为它对我来说更容易跟踪所使用的特定过滤器。有没有更好的方法来解决这个问题?
public class EntityExistsFilter<T> : IAsyncActionFilter where T : class
{
private readonly IEntityExistsService<T> _entityExistsService;
private int _id;
public EntityExistsFilter(IEntityExistsService<T> entityExistsService)
{
_entityExistsService = entityExistsService;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (context.ActionArguments.ContainsKey("id"))
{
//try and cast the id to an int
var id = int.TryParse(context.ActionArguments["id"].ToString(), out _id);
//if cast succeeds
if (id)
{
var entityExists = await _entityExistsService.EntityExists(_id);
//if entity does not exist - return not found result
if (!entityExists)
{
context.Result = new NotFoundResult();
return;
}
}
}
await next();
}
}
}