MethodInfo matched = _selector.FindActionMethod(controllerContext, actionName);
return new ReflectedActionDescriptor(matched, actionName, this);
_selector.FindActionMethod(controllerContext, actionName); 这句就是找到我们需要Action对应的MethodInfo。
复制代码 代码如下:
public MethodInfo FindActionMethod(ControllerContext controllerContext, string actionName) {
List<MethodInfo> methodsMatchingName = GetMatchingAliasedMethods(controllerContext, actionName);
methodsMatchingName.AddRange(NonAliasedMethods[actionName]);
List<MethodInfo> finalMethods = RunSelectionFilters(controllerContext, methodsMatchingName);
switch (finalMethods.Count) {
case 0:
return null;
case 1:
return finalMethods[0];
default:
throw CreateAmbiguousMatchException(finalMethods, actionName);
}
}
循环每个MethodInfo,查找它们的自定义的ActionMethodSelectorAttribute特性,如果有只返回验证通过的特性。看到ReflectedAttributeCache.GetActionMethodSelectorAttributes(methodInfo)这样的代码感觉由于缓存有关,
复制代码 代码如下:
private static ReadOnlyCollection<TAttribute> GetAttributes<TMemberInfo, TAttribute>(ConcurrentDictionary<TMemberInfo, ReadOnlyCollection<TAttribute>> lookup, TMemberInfo memberInfo)
where TAttribute : Attribute
where TMemberInfo : MemberInfo {
return lookup.GetOrAdd(memberInfo, mi => new ReadOnlyCollection<TAttribute>((TAttribute[])memberInfo.GetCustomAttributes(typeof(TAttribute), inherit: true)));
}
ReflectedAttributeCache这个类有几个缓存字典:
ConcurrentDictionary<MethodInfo, ReadOnlyCollection<ActionMethodSelectorAttribute>>
ConcurrentDictionary<MethodInfo, ReadOnlyCollection<ActionNameSelectorAttribute>>
ConcurrentDictionary<MethodInfo, ReadOnlyCollection<FilterAttribute>>
ConcurrentDictionary<Type, ReadOnlyCollection<FilterAttribute>>
默认实现ActionMethodSelectorAttribute类主要有以下几个
AcceptVerbsAttribute
HttpDeleteAttribute
HttpGetAttribute
HttpPostAttribute
HttpPutAttribute
NonActionAttribute
AcceptVerbsAttribute
剩下的就是直接实例一个ReflectedActionDescriptor对象了,这个也没什么特殊,只是里面有一个验证方法
复制代码 代码如下:
if (validateMethod) {
string failedMessage = VerifyActionMethodIsCallable(methodInfo);
if (failedMessage != null) {
throw new ArgumentException(failedMessage, "methodInfo");
}
}
用来验证该方法是否可以执行,以下几种情况经不会通过,(1)方法是静态方法(2)方法的实例类型不是ControllerBase(3)是否包含泛型参数如 public ActionResult Index<T>()是非法的,但 public ActionResult Index(List<string> aa)是合法(4)参数中不能含有Ref和out。
这篇文章说的很散,我们需要注意一点微软在mvc里面缓存做的很好了,在前面个将获取ControllerTyper时它是有缓存的,一次读取当前程序集所有的ControllerType,在这里提到了一个DescriptorCache 缓存每次调用的ControllerType->ReflectedControllerDescriptor,而ReflectedControllerDescriptor实例会一次去读该Controller的所有Action方法;这里还有一个ReflectedAttributeCache,缓存每次调用MethodInfo的所有特性(ActionMethodSelectorAttribute、ActionNameSelectorAttribute、FilterAttribute),当然FilterAttribute特性还可以在类上面。
您可能感兴趣的文章: