public
abstract
class
Controller
{
public
virtual
void
OnActionExecuting(MethodInfo action)
{
}
public
virtual
void
OnActionExecuted(MethodInfo action)
{
}
public
virtual
void
OnActionError(MethodInfo action, Exception ex)
{
}
}
public
abstract
class
FilterAttribute : Attribute
{
public
abstract
string
FilterType {
get``; }
public
abstract
void
Execute(Controller ctrller,
object
extData);
}
public
class
ActionExecutingFilter : FilterAttribute
{
public
override
string
FilterType =>
"BEFORE"``;
public
override
void
Execute(Controller ctrller,
object
extData)
{
Console.WriteLine($``"我是在{ctrller.GetType().Name}.ActionExecutingFilter中拦截发出的消息!-{DateTime.Now.ToString()}"``);
}
}
public
class
ActionExecutedFilter : FilterAttribute
{
public
override
string
FilterType =>
"AFTER"``;
public
override
void
Execute(Controller ctrller,
object
extData)
{
Console.WriteLine($``"我是在{ctrller.GetType().Name}.ActionExecutedFilter中拦截发出的消息!-{DateTime.Now.ToString()}"``);
}
}
public
class
ActionErrorFilter : FilterAttribute
{
public
override
string
FilterType =>
"EXCEPTION"``;
public
override
void
Execute(Controller ctrller,
object
extData)
{
Console.WriteLine($``"我是在{ctrller.GetType().Name}.ActionErrorFilter中拦截发出的消息!-{DateTime.Now.ToString()}-Error Msg:{(extData as Exception).Message}"``);
}
}
public
class
AppContext
{
private
static
readonly
Type ControllerType =
typeof``(Controller);
private
static
readonly
Dictionary<``string``, Type> matchedControllerTypes =
new
Dictionary<``string``, Type>();
private
static
readonly
Dictionary<``string``, MethodInfo> matchedControllerActions =
new
Dictionary<``string``, MethodInfo>();
private
Dictionary<``string``,``string``[]> routeTemplates =
new
Dictionary<``string``,
string``[]>();
public
void
AddExecRouteTemplate(``string
execRouteTemplate)
{
if
(!Regex.IsMatch(execRouteTemplate,
"{controller}"``, RegexOptions.IgnoreCase))
{
throw
new
ArgumentException(``"执行路由模板不正确,缺少{controller}"``);
}
if
(!Regex.IsMatch(execRouteTemplate,
"{action}"``, RegexOptions.IgnoreCase))
{
throw
new
ArgumentException(``"执行路由模板不正确,缺少{action}"``);
}
string``[] keys = Regex.Matches(execRouteTemplate,
@"(?<={)\w+(?=})"``, RegexOptions.IgnoreCase).Cast<Match>().Select(c => c.Value.ToLower()).ToArray();
routeTemplates.Add(execRouteTemplate,keys);
}
public
object
Run(``string
execRoute)
{
string
ctrller =
null``;
string
actionName =
null``;
ArrayList args =
null``;
Type controllerType =
null``;
bool
findResult =
false``;
foreach
(var r
in
routeTemplates)
{
string``[] keys = r.Value;
string
execRoutePattern = Regex.Replace(r.Key,
@"{(?<key>\w+)}"``, (m) =>
string``.Format(``@"(?<{0}>.[^/\\]+)"``, m.Groups[``"key"``].Value.ToLower()), RegexOptions.IgnoreCase);
args =
new
ArrayList();
if
(Regex.IsMatch(execRoute, execRoutePattern))
{
var match = Regex.Match(execRoute, execRoutePattern);
for
(``int
i = 0; i < keys.Length; i++)
{
if
(``"controller"``.Equals(keys[i], StringComparison.OrdinalIgnoreCase))
{
ctrller = match.Groups[``"controller"``].Value;
}
else
if
(``"action"``.Equals(keys[i], StringComparison.OrdinalIgnoreCase))
{
actionName = match.Groups[``"action"``].Value;
}
else
{
args.Add(match.Groups[keys[i]].Value);
}
}
if
((controllerType = FindControllerType(ctrller)) !=
null
&& FindAction(controllerType, actionName, args.ToArray()) !=
null``)
{
findResult =
true``;
break``;
}
}
}
if
(findResult)
{
return
Process(ctrller, actionName, args.ToArray());
}
else
{
throw
new
Exception($``"在已配置的路由模板列表中未找到与该执行路由相匹配的路由信息:{execRoute}"``);
}
}
public
object
Process(``string
ctrller,
string
actionName,
params
object``[] args)
{
Type matchedControllerType = FindControllerType(ctrller);
if
(matchedControllerType ==
null``)
{
throw
new
ArgumentException($``"未找到类型为{ctrller}的Controller类型"``);
}
object
execResult =
null``;
if
(matchedControllerType !=
null``)
{
var matchedController = (Controller)Activator.CreateInstance(matchedControllerType);
MethodInfo action = FindAction(matchedControllerType, actionName, args);
if
(action ==
null``)
{
throw
new
ArgumentException($``"在{matchedControllerType.FullName}中未找到与方法名:{actionName}及参数个数:{args.Count()}相匹配的方法"``);
}
var filters = action.GetCustomAttributes<FilterAttribute>(``true``);
List<FilterAttribute> execBeforeFilters =
new
List<FilterAttribute>();
List<FilterAttribute> execAfterFilters =
new
List<FilterAttribute>();
List<FilterAttribute> exceptionFilters =
new
List<FilterAttribute>();
if
(filters !=
null
&& filters.Count() > 0)
{
execBeforeFilters = filters.Where(f => f.FilterType ==
"BEFORE"``).ToList();
execAfterFilters = filters.Where(f => f.FilterType ==
"AFTER"``).ToList();
exceptionFilters = filters.Where(f => f.FilterType ==
"EXCEPTION"``).ToList();
}
try
{
matchedController.OnActionExecuting(action);
if
(execBeforeFilters !=
null
&& execBeforeFilters.Count > 0)
{
execBeforeFilters.ForEach(f => f.Execute(matchedController,
null``));
}
var mParams = action.GetParameters();
object``[] newArgs =
new
object``[args.Length];
for
(``int
i = 0; i < mParams.Length; i++)
{
newArgs[i] = Convert.ChangeType(args[i], mParams[i].ParameterType);
}
execResult = action.Invoke(matchedController, newArgs);
matchedController.OnActionExecuted(action);
if
(execBeforeFilters !=
null
&& execBeforeFilters.Count > 0)
{
execAfterFilters.ForEach(f => f.Execute(matchedController,
null``));
}
}
catch
(Exception ex)
{
matchedController.OnActionError(action, ex);
if
(exceptionFilters !=
null
&& exceptionFilters.Count > 0)
{
exceptionFilters.ForEach(f => f.Execute(matchedController, ex));
}
}
}
return
execResult;
}
private
Type FindControllerType(``string
ctrller)
{
Type matchedControllerType =
null``;
if
(!matchedControllerTypes.ContainsKey(ctrller))
{
var assy = Assembly.GetAssembly(``typeof``(Controller));
foreach
(var m
in
assy.GetModules(``false``))
{
foreach
(var t
in
m.GetTypes())
{
if
(ControllerType.IsAssignableFrom(t) && !t.IsAbstract)
{
if
(t.Name.Equals(ctrller, StringComparison.OrdinalIgnoreCase) || t.Name.Equals($``"{ctrller}Controller"``, StringComparison.OrdinalIgnoreCase))
{
matchedControllerType = t;
matchedControllerTypes[ctrller] = matchedControllerType;
break``;
}
}
}
}
}
else
{
matchedControllerType = matchedControllerTypes[ctrller];
}
return
matchedControllerType;
}
private
MethodInfo FindAction(Type matchedControllerType,
string
actionName,
object``[] args)
{
string
ctrlerWithActionKey = $``"{matchedControllerType.FullName}.{actionName}"``;
MethodInfo action =
null``;
if
(!matchedControllerActions.ContainsKey(ctrlerWithActionKey))
{
if
(args ==
null``) args =
new
object``[0];
foreach
(var m
in
matchedControllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public))
{
if
(m.Name.Equals(actionName, StringComparison.OrdinalIgnoreCase) && m.GetParameters().Length == args.Length)
{
action = m;
matchedControllerActions[ctrlerWithActionKey] = action;
break``;
}
}
}
else
{
action = matchedControllerActions[ctrlerWithActionKey];
}
return
action;
}
}