Frage

Ist es möglich, alle Controller zur Verfügung zu einem Controller zu bekommen?
Was ich tun möchte, ist eine Liste aller Reglertypen in der Anwendung, aber in einer konsistenten Art und Weise.

Damit alle Controller ich sind die gleichen, die Standard-Anforderungs Auflösung verwendet wird.

(Die eigentliche Aufgabe ist es, alle Aktionsmethoden zu finden, die ein bestimmtes Attribut hat).

War es hilfreich?

Lösung

Sie können mit Reflexion alle Klassen in einer Baugruppe aufzuzählen, und filtern, um nur Klassen von Controller-Klasse erben.

Die beste Referenz ist asp.net Mvc Quellcode . Werfen Sie einen Blick der Implementierungen von ControllerTypeCache und ActionMethodSelector Klasse. ControllerTypeCache zeigt, wie alle Controller-Klassen zur Verfügung zu bekommen.

       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);
                    }
                }
            }
        }

Und ActionMethodSelector zeigt, wie Sie überprüfen, ob ein Attribut method gewünscht hat.

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;
        }

Andere Tipps

Ich glaube nicht, es ist möglich, eine einfache Antwort auf diese Frage zu geben, weil es auf einer Menge verschiedenen Dinge abhängt, einschließlich der Umsetzung von IControllerFactory.

Zum Beispiel, wenn Sie eine vollständig maßgeschneiderte IControllerFactory Implementierung haben, sind alle Wetten ab, weil sie verwenden können alle Art von Mechanismus-Controller-Instanzen zu erstellen.

Allerdings sieht die DefaultControllerFactory nach dem entsprechenden Controllertyp in allen in der Routecollection definiert Baugruppen (in global.asax konfigurierte).

In diesem Fall könnten Sie eine Schleife durch alle Baugruppen mit der Routecollection zugeordnet ist, und sucht Controller in jedem.

Finding-Controller in einer bestimmten Anordnung ist relativ einfach:

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

wo asm ist eine Assembly-Instanz.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top