Filter discovery
This commit is contained in:
parent
dc6b1b1a4a
commit
75bccbae21
|
|
@ -0,0 +1,21 @@
|
|||
using Microsoft.AspNet.Mvc;
|
||||
using MvcSample.Models;
|
||||
|
||||
namespace MvcSample
|
||||
{
|
||||
// Expected order in descriptor - object -> int -> string
|
||||
// TODO: Add a real filter here
|
||||
[ServiceFilter(typeof(object), Order = 1)]
|
||||
[ServiceFilter(typeof(string))]
|
||||
public class FiltersController : Controller
|
||||
{
|
||||
private readonly User _user = new User() { Name = "User Name", Address = "Home Address" };
|
||||
|
||||
// TODO: Add a real filter here
|
||||
[ServiceFilter(typeof(int))]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View("MyView", _user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,5 +3,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
public interface IFilter
|
||||
{
|
||||
// Marker only interface to any IFilter gets picked up by the DefaultActionDescriptorProvider
|
||||
int Order { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public interface IServiceFilter : IFilter
|
||||
{
|
||||
Type ServiceType { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
||||
[DebuggerDisplay("ServiceFilter: Type={ServiceType} Order={Order}")]
|
||||
public class ServiceFilterAttribute : Attribute, IServiceFilter
|
||||
{
|
||||
public ServiceFilterAttribute(Type type)
|
||||
{
|
||||
ServiceType = type;
|
||||
}
|
||||
|
||||
public Type ServiceType { get; private set; }
|
||||
|
||||
public int Order { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,8 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
foreach (var cd in controllerDescriptors)
|
||||
{
|
||||
var controllerFilters = GetOrderedFilterAttributes(cd.ControllerTypeInfo);
|
||||
|
||||
foreach (var methodInfo in cd.ControllerTypeInfo.DeclaredMethods)
|
||||
{
|
||||
var actionInfos = _conventions.GetActions(methodInfo);
|
||||
|
|
@ -54,13 +56,24 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
foreach (var actionInfo in actionInfos)
|
||||
{
|
||||
yield return BuildDescriptor(cd, methodInfo, actionInfo);
|
||||
yield return BuildDescriptor(cd, methodInfo, actionInfo, controllerFilters);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ReflectedActionDescriptor BuildDescriptor(ControllerDescriptor controllerDescriptor, MethodInfo methodInfo, ActionInfo actionInfo)
|
||||
private IFilter[] GetOrderedFilterAttributes(MemberInfo memberInfo)
|
||||
{
|
||||
var attributes = memberInfo.GetCustomAttributes(inherit: true);
|
||||
var filters = attributes.OfType<IFilter>().OrderByDescending(filter => filter.Order);
|
||||
|
||||
return filters.ToArray();
|
||||
}
|
||||
|
||||
private ReflectedActionDescriptor BuildDescriptor(ControllerDescriptor controllerDescriptor,
|
||||
MethodInfo methodInfo,
|
||||
ActionInfo actionInfo,
|
||||
IFilter[] controllerFilters)
|
||||
{
|
||||
var ad = new ReflectedActionDescriptor
|
||||
{
|
||||
|
|
@ -85,7 +98,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
if (actionInfo.RequireActionNameMatch)
|
||||
{
|
||||
ad.RouteConstraints.Add(new RouteDataActionConstraint("action", actionInfo.ActionName));
|
||||
ad.RouteConstraints.Add(new RouteDataActionConstraint("action", actionInfo.ActionName));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -94,7 +107,41 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
ad.Parameters = methodInfo.GetParameters().Select(p => _parameterDescriptorFactory.GetDescriptor(p)).ToList();
|
||||
|
||||
// TODO: add ordering support such that action filters are ahead of controller filters if they have the same order
|
||||
var actionFilters = GetOrderedFilterAttributes(methodInfo);
|
||||
|
||||
ad.Filters = MergeSorted(actionFilters, controllerFilters);
|
||||
|
||||
return ad;
|
||||
}
|
||||
|
||||
internal List<IFilter> MergeSorted(IFilter[] actionFilters, IFilter[] controllerFilters)
|
||||
{
|
||||
var list = new List<IFilter>();
|
||||
|
||||
var count = actionFilters.Length + controllerFilters.Length;
|
||||
|
||||
for (int i = 0, j = 0; i + j < count; )
|
||||
{
|
||||
if (i >= actionFilters.Length)
|
||||
{
|
||||
list.Add(controllerFilters[j++]);
|
||||
}
|
||||
else if (j >= controllerFilters.Length)
|
||||
{
|
||||
list.Add(actionFilters[i++]);
|
||||
}
|
||||
else if (actionFilters[i].Order >= controllerFilters[j].Order)
|
||||
{
|
||||
list.Add(actionFilters[i++]);
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(controllerFilters[j++]);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue