|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Web.Mvc;
using MvcCallInterceptors.Controllers;
namespace MvcCallInterceptors.Interceptors
{
/*
* InterceptorsRegistry is a class which takes care of registration of interceptor methods,
* and get interceptors methods for a method call in the controller.
*/
public sealed class InterceptorsRegistry
{
static Dictionary<string, List<ActionInterceptor>> Interceptors = new Dictionary<string, List<ActionInterceptor>>();
/// <summary>
/// This method registers all interceptor methods in the given class type which are decorated with ActionInterceptorAttribute.
/// </summary>
/// <typeparam name="T"></typeparam>
public static void RegisterInterceptors<T>() where T : IInterceptorMvcController
{
//Challenge to stop recursive call if they are there
var interceptedByViewControllerType = typeof(T);
var members = interceptedByViewControllerType.FindMembers(MemberTypes.Method,
BindingFlags.Instance | BindingFlags.Public, new MemberFilter(SearchForInterceptorAttribute),
typeof(ActionInterceptorAttribute));
foreach (var member in members)
{
//Register either with
var attribute = member.GetCustomAttributes(typeof(ActionInterceptorAttribute), false)[0] as ActionInterceptorAttribute;
var methodInfo = member as MethodInfo;
// To restrict recursive calling this is the simplest way I found and ActionResult return type is kind of
// overhead to pass result to subsequent interceptors and convert to object again.
if(methodInfo.ReturnType==typeof(ActionResult) || methodInfo.ReturnType.IsSubclassOf(typeof(ActionResult)))
{
throw new Exception("ActionResult methods cannot be act as interceptor");
}
if (methodInfo.GetParameters().Length !=2 || methodInfo.GetParameters()[0].ParameterType!=typeof(InterceptorParasDictionary<string,object>) ||
methodInfo.GetParameters()[1].ParameterType != typeof(object))
{
throw new Exception("Interceptor method should have only two parameters namely InterceptorParasDictionary<string,object> and object types");
}
var key = ((attribute.InterceptionForViewControllerType == null ? attribute.ViewName.ToString() : attribute.InterceptionForViewControllerType.FullName)
+ ";" + attribute.ActionName).ToLower();
// In one interceptor (or interceptor controller) class if somebody tries to register more than one methods as interceptors for one action method
// of other controller then it's not possible, such kind of scenario should not be happened and can be restricted by registering interceptor methods
// by using one thing only i.e. either ViewName or InterceptionForViewController but not both.
// And below condtion would take care of this.
var actionInterceptor = new ActionInterceptor(interceptedByViewControllerType, attribute, member as MethodInfo);
if (Interceptors.ContainsKey(key) && Interceptors[key].All((inc)=>inc.Equals(actionInterceptor)))
{
throw new Exception(string.Format("Duplicate interceptor entry for action {0} in {1}.",attribute.ActionName,
attribute.InterceptionForViewControllerType==null?"View Name "+ attribute.ViewName : "Controller "+ attribute.InterceptionForViewControllerType.FullName ));
}
if (!Interceptors.ContainsKey(key) || Interceptors[key] == null)
{
Interceptors[key] = new List<ActionInterceptor>();
}
Interceptors[key].Add(actionInterceptor);
}
}
public static IEnumerable<ActionInterceptor> GetInterceptors(BaseMvcController controller, ActionDescriptor actionDescriptor)
{
var key1 = (controller.GetType().FullName + ";" + actionDescriptor.ActionName).ToLower();
var key2 = (controller.ViewName + ";" + actionDescriptor.ActionName).ToLower();
var result1 = new List<ActionInterceptor>();
var result2 = new List<ActionInterceptor>();
if (InterceptorsRegistry.Interceptors.ContainsKey(key1))
{
result1 = InterceptorsRegistry.Interceptors[key1];
}
if (InterceptorsRegistry.Interceptors.ContainsKey(key2))
{
result2 = InterceptorsRegistry.Interceptors[key2];
}
var commonCount = result1.Intersect(result2, new ActionInterceptorComparer()).Count();
if (commonCount > 0)
{
throw new Exception("An Interceptor registered multiple times");
}
var result = result1.Union(result2, new ActionInterceptorComparer());
return result;
}
private static bool SearchForInterceptorAttribute(MemberInfo objMemberInfo, Object objSearch)
{
// Compare the name of the member function with the filter criteria.
return objMemberInfo.GetCustomAttributes(typeof(ActionInterceptorAttribute), false).Length > 0;
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.