Domanda

E 'possibile ottenere tutti i controller disponibili per un ControllerFactory?
Quello che voglio fare è ottenere una lista di tutti i tipi di controller di applicazione, ma in modo coerente.

In modo che tutti i controller ricevo sono quelle della risoluzione stessa richiesta di default sta usando.

(Il compito attuale è quello di trovare tutti i metodi di azione che hanno un determinato attributo).

È stato utile?

Soluzione

È possibile utilizzare la riflessione per enumerare tutte le classi di un assieme, e filtrare solo le classi ereditano dalla classe Controller.

Il miglior riferimento è asp.net codice sorgente mvc . Date un'occhiata delle implementazioni di ControllerTypeCache e ActionMethodSelector classe . ControllerTypeCache mostra come ottenere tutte le classi controller disponibili.

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

E ActionMethodSelector mostra come controllare se un metodo ha desiderato attributo.

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

Altri suggerimenti

Non credo che sia possibile dare una risposta semplice a questa domanda, perché dipende da un sacco di cose diverse, tra cui l'attuazione di IControllerFactory.

Per esempio, se si dispone di un'implementazione IControllerFactory completamente su misura, tutte le scommesse sono spenti, perché può usare qualsiasi sorta di meccanismo per creare istanze del controller.

Tuttavia, il DefaultControllerFactory si occupa del tipo di controllo appropriato in tutte le assemblee definiti nel RouteCollection (configurato in global.asax).

In questo caso, si potrebbe scorrere tutti i gruppi associati al RouteCollection, e cercare in ogni controller.

Trovare controller in un dato complesso è relativamente facile:

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

dove asm è un'istanza di montaggio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top