我对 Kiran Challa 的回答中的解决方案有一些问题。这是我的修改。
问题出在方法上
private IEnumerable<FilterInfo> OrderFilters(IEnumerable<IFilter> filters, FilterScope scope)
{
return filters.OfType<IOrderedFilter>()
.OrderBy(filter => filter.Order)
.Select(instance => new FilterInfo(instance, scope));
}
如您所见,只有实现的过滤器IOrderedFilter
才会返回。我有一个第三方属性被删除,因此没有执行。
所以我有两种可能的解决方案。
- 使用继承来创建第三方属性的扩展版本,以使其也实现
IOrderFilter
。
- 更改方法以对待每个属性都没有
IOrderFilter
像IOrderFilter
订单号为 0 的属性那样实现,并将其与IOrderFilter
属性组合,排序并返回它们。
第二种解决方案更好,因为它允许我将我的IOrderFilter
属性放在未实现的第三方属性之前IOrderFilter
。
样本
[NonOrderableThirdPartyAttribute]
[OrderableAttributeA(Order = -1)]
[OrderableAttributeB(Order = 1)]
[OrderableAttributeC(Order = 2)]
public async Task<IHttpActionResult> Post(... request)
{
// do something
}
所以执行将是
- 可订购属性A
- NonOrderableThirdParty 属性
- 可订购属性B
- 可订购属性C
所以这是修改后的代码
public class OrderedFilterProvider : IFilterProvider
{
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
// controller-specific
var controllerSpecificFilters = OrderFilters(actionDescriptor.ControllerDescriptor.GetFilters(), FilterScope.Controller);
// action-specific
var actionSpecificFilters = OrderFilters(actionDescriptor.GetFilters(), FilterScope.Action);
return controllerSpecificFilters.Concat(actionSpecificFilters);
}
private IEnumerable<FilterInfo> OrderFilters(IEnumerable<IFilter> filters, FilterScope scope)
{
// get all filter that dont implement IOrderedFilter and give them order number of 0
var notOrderableFilter = filters.Where(f => !(f is IOrderedFilter))
.Select(instance => new KeyValuePair<int, FilterInfo>(0, new FilterInfo(instance, scope)));
// get all filter that implement IOrderFilter and give them order number from the instance
var orderableFilter = filters.OfType<IOrderedFilter>().OrderBy(filter => filter.Order)
.Select(instance => new KeyValuePair<int, FilterInfo>(instance.Order, new FilterInfo(instance, scope)));
// concat lists => order => return
return notOrderableFilter.Concat(orderableFilter).OrderBy(x => x.Key).Select(y => y.Value);
}
}