ASP.NET MVC:获取所有控制器

时间:2009-12-10 11:30:43

标签: asp.net-mvc controllers

是否可以将所有控制器都用于ControllerFactory? 我想要做的是获取应用程序中所有控制器类型的列表,但是以一致的方式。

因此我得到的所有控制器都是默认的请求解析使用的。

(实际任务是找到具有给定属性的所有操作方法)。

2 个答案:

答案 0 :(得分:12)

您可以使用反射来枚举程序集中的所有类,并仅过滤从Controller类继承的类。

最佳参考是asp.net mvc source code。看一下ControllerTypeCacheActionMethodSelector类的实现。 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;
        }

答案 1 :(得分:7)

我认为不可能对这个问题给出一个简单的答案,因为它取决于很多不同的东西,包括IControllerFactory的实现。

例如,如果你有一个完全自定义构建的IControllerFactory实现,那么所有的赌注都会关闭,因为它可能会使用任何种机制来创建Controller实例。

但是,DefaultControllerFactory在RouteCollection中定义的所有程序集中查找相应的Controller类型(在global.asax中配置)。

在这种情况下,您可以循环遍历与RouteCollection关联的所有程序集,并在每个程序集中查找控制器。

在给定的程序集中查找控制器相对容易:

var controllerTypes = from t in asm.GetExportedTypes()
                      where typeof(IController).IsAssignableFrom(t)
                      select t;

其中asm是程序集实例。