private List<FilterItem> BuildFilterItems(Type type, MethodInfo method, FilterChainKind kind)
{
var filterItems = new List<FilterItem>();
var filterPerInvokeIndex = 0;
// scan all filters for this method and construct a list of filter item
// discard filters that doesn't provide a exact filter (such as a filter doesn't have OnPreRequest on kind=Request)
var filterFactories = type.GetCustomAttributes().Concat(method.GetCustomAttributes()).OfType<IFilterFactory>();
foreach (var filterFactory in filterFactories)
{
FilterItem filterItem = null;
if (filterFactory is IFilterPerClassFactory)
{
var factoryType = filterFactory.GetType();
if (_perClassFilterItemTable.TryGetValue(factoryType, out filterItem) == false)
{
var factory = (IFilterPerClassFactory)filterFactory;
factory.Setup(type);
var filter = factory.CreateInstance();
if (CheckFilterKind(filter, kind))
{
filterItem = new FilterItem(kind, filterFactory, filter, (_, x) => filter);
_perClassFilterItemTable.Add(factoryType, filterItem);
}
}
else if (filterItem.Kind != kind)
{
filterItem = null;
}
}
else if (filterFactory is IFilterPerClassMethodFactory)
{
var factory = (IFilterPerClassMethodFactory)filterFactory;
factory.Setup(type, method);
var filter = factory.CreateInstance();
if (CheckFilterKind(filter, kind))
{
filterItem = new FilterItem(kind, filterFactory, filter, (_, x) => filter);
}
}
else if (filterFactory is IFilterPerInstanceFactory)
{
var factoryType = filterFactory.GetType();
if (_perInstanceFilterItemTable.TryGetValue(factoryType, out filterItem) == false)
{
var factory = ((IFilterPerInstanceFactory)filterFactory);
factory.Setup(type);
var filter = factory.CreateInstance(null);
if (CheckFilterKind(filter, kind))
{
var arrayIndex = _perInstanceFilterCreators.Count;
_perInstanceFilterCreators.Add(a => factory.CreateInstance(a));
filterItem = new FilterItem(kind, filterFactory, filter,
(provider, _) => provider.GetFilter(arrayIndex));
_perInstanceFilterItemTable.Add(factoryType, filterItem);
}
}
else if (filterItem.Kind != kind)
{
filterItem = null;
}
}
else if (filterFactory is IFilterPerInstanceMethodFactory)
{
var factory = ((IFilterPerInstanceMethodFactory)filterFactory);
factory.Setup(type, method);
var filter = factory.CreateInstance(null);
if (CheckFilterKind(filter, kind))
{
var arrayIndex = _perInstanceFilterCreators.Count;
_perInstanceFilterCreators.Add(a => factory.CreateInstance(a));
filterItem = new FilterItem(kind, filterFactory, filter,
(provider, _) => provider.GetFilter(arrayIndex));
}
}
else if (filterFactory is IFilterPerInvokeFactory)
{
var factory = ((IFilterPerInvokeFactory)filterFactory);
factory.Setup(type, method);
var filter = factory.CreateInstance(null, null);
if (CheckFilterKind(filter, kind))
{
var arrayIndex = filterPerInvokeIndex++;
filterItem = new FilterItem(kind, filterFactory, filter,
(_, filters) => filters[arrayIndex], filterPerInvokeIndex);
}
}
if (filterItem != null)
filterItems.Add(filterItem);
}
return filterItems;
}