У меня были некоторые проблемы с решением из ответа Киран Чалла. Вот моя модификация.
Проблема была в методе
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
}
Так что казнь будет
- ЗаказываемыйАтрибутА
- NonOrderableThirdPartyAttribute
- ЗаказываемыйАтрибут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);
}
}
person
dknaack
schedule
01.03.2016