是否可以让 ControllerFactory 可用的所有控制器?
我想要做的是获取应用程序中所有控制器类型的列表,但以一致的方式。
这样我得到的所有控制器都是默认请求解析使用的相同控制器。
(实际任务是找到所有具有给定属性的操作方法)。
是否可以让 ControllerFactory 可用的所有控制器?
我想要做的是获取应用程序中所有控制器类型的列表,但以一致的方式。
这样我得到的所有控制器都是默认请求解析使用的相同控制器。
(实际任务是找到所有具有给定属性的操作方法)。
您可以使用反射来枚举程序集中的所有类,并仅过滤从 Controller 类继承的类。
最好的参考是asp.net mvc 源代码。看看ControllerTypeCache和ActionMethodSelector类的实现。ControllerTypeCache 展示了如何获取所有可用的控制器类。
internal static bool IsControllerType(Type t) {
return
t != null &&
t.IsPublic &&
t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) &&
!t.IsAbstract &&
typeof(IController).IsAssignableFrom(t);
}
public void EnsureInitialized(IBuildManager buildManager) {
if (_cache == null) {
lock (_lockObj) {
if (_cache == null) {
List<Type> controllerTypes = GetAllControllerTypes(buildManager);
var groupedByName = controllerTypes.GroupBy(
t => t.Name.Substring(0, t.Name.Length - "Controller".Length),
StringComparer.OrdinalIgnoreCase);
_cache = groupedByName.ToDictionary(
g => g.Key,
g => g.ToLookup(t => t.Namespace ?? String.Empty, StringComparer.OrdinalIgnoreCase),
StringComparer.OrdinalIgnoreCase);
}
}
}
}
ActionMethodSelector 展示了如何检查方法是否具有所需的属性。
private static List<MethodInfo> RunSelectionFilters(ControllerContext controllerContext, List<MethodInfo> methodInfos) {
// remove all methods which are opting out of this request
// to opt out, at least one attribute defined on the method must return false
List<MethodInfo> matchesWithSelectionAttributes = new List<MethodInfo>();
List<MethodInfo> matchesWithoutSelectionAttributes = new List<MethodInfo>();
foreach (MethodInfo methodInfo in methodInfos) {
ActionMethodSelectorAttribute[] attrs = (ActionMethodSelectorAttribute[])methodInfo.GetCustomAttributes(typeof(ActionMethodSelectorAttribute), true /* inherit */);
if (attrs.Length == 0) {
matchesWithoutSelectionAttributes.Add(methodInfo);
}
else if (attrs.All(attr => attr.IsValidForRequest(controllerContext, methodInfo))) {
matchesWithSelectionAttributes.Add(methodInfo);
}
}
// if a matching action method had a selection attribute, consider it more specific than a matching action method
// without a selection attribute
return (matchesWithSelectionAttributes.Count > 0) ? matchesWithSelectionAttributes : matchesWithoutSelectionAttributes;
}
我认为不可能对这个问题给出一个简单的答案,因为它取决于很多不同的东西,包括 IControllerFactory 的实现。
例如,如果您有一个完全定制的 IControllerFactory 实现,那么所有的赌注都没有了,因为它可能使用任何类型的机制来创建 Controller 实例。
但是,DefaultControllerFactory 会在 RouteCollection 中定义的所有程序集中(在 global.asax 中配置)处理适当的控制器类型。
在这种情况下,您可以遍历与 RouteCollection 关联的所有程序集,并在每个程序集中查找控制器。
在给定的程序集中查找控制器相对容易:
var controllerTypes = from t in asm.GetExportedTypes()
where typeof(IController).IsAssignableFrom(t)
select t;
asm
装配实例在哪里。