【问题标题】:ASP.NET MVC: Get all controllersASP.NET MVC:获取所有控制器
【发布时间】:2009-12-10 11:30:42
【问题描述】:

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

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

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

【问题讨论】:

    标签: asp.net-mvc controllers


    【解决方案1】:

    您可以使用反射来枚举程序集中的所有类,并仅过滤从 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;
            }
    

    【讨论】:

    • 内部,我希望他们没有这样做。但是好的,这就是答案。
    【解决方案2】:

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

    例如,如果您有一个完全定制的 IControllerFactory 实现,那么所有的赌注都没有,因为它可能使用任何种机制来创建控制器实例。

    但是,DefaultControllerFactory 会在 RouteCollection 中定义的所有程序集中(在 global.asax 中配置)处理适当的控制器类型。

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

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

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

    其中asm 是一个Assembly 实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-05
      • 2011-01-09
      • 2010-09-29
      • 2016-09-22
      • 1970-01-01
      • 2017-07-15
      • 2019-08-31
      • 2023-04-05
      相关资源
      最近更新 更多