Вопрос

Возможно ли получить все контроллеры, доступные для ControllerFactory?
Что я хочу сделать, это получить список всех типов контроллеров в приложении, но согласованным образом.

Таким образом, все контроллеры, которые я получаю, являются теми же, которые используются для разрешения запросов по умолчанию.

(Фактическая задача состоит в том, чтобы найти все методы действия, которые имеют данный атрибут).

Это было полезно?

Решение

Вы можете использовать отражение для перечисления всех классов в сборке и фильтрации только классов, наследуемых от класса контроллера.

Лучшая ссылка - это asp.net исходный код mvc.Взгляните на реализации ControllerTypeCache - Кэш типа контроллера и Actionметодселектор класс.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);
                    }
                }
            }
        }

И ActionMethod Selector показывает, как проверить, имеет ли метод желаемый атрибут.

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, все ставки отменяются, поскольку она может использовать Любой своего рода механизм для создания экземпляров контроллера.

Однако DefaultControllerFactory следит за соответствующим типом контроллера во всех сборках, определенных в RouteCollection (настроенных в global.asax).

В этом случае вы могли бы перебрать все сборки, связанные с RouteCollection, и искать контроллеры в каждой.

Найти контроллеры в данной сборке относительно просто:

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

где asm является экземпляром Сборки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top