1 /* ****************************************************************************
\r
3 * Copyright (c) Microsoft Corporation. All rights reserved.
\r
5 * This software is subject to the Microsoft Public License (Ms-PL).
\r
6 * A copy of the license can be found in the license.htm file included
\r
7 * in this distribution.
\r
9 * You must not remove this notice, or any other, from this software.
\r
11 * ***************************************************************************/
\r
13 namespace System.Web.Mvc {
\r
15 using System.Collections;
\r
16 using System.Collections.Generic;
\r
18 using System.Reflection;
\r
20 internal sealed class ControllerTypeCache {
\r
22 private Dictionary<string, ILookup<string, Type>> _cache;
\r
23 private object _lockObj = new object();
\r
25 internal int Count {
\r
28 foreach (var lookup in _cache.Values) {
\r
29 foreach (var grouping in lookup) {
\r
30 count += grouping.Count();
\r
37 public void EnsureInitialized(IBuildManager buildManager) {
\r
38 if (_cache == null) {
\r
40 if (_cache == null) {
\r
41 List<Type> controllerTypes = GetAllControllerTypes(buildManager);
\r
42 var groupedByName = controllerTypes.GroupBy(
\r
43 t => t.Name.Substring(0, t.Name.Length - "Controller".Length),
\r
44 StringComparer.OrdinalIgnoreCase);
\r
45 _cache = groupedByName.ToDictionary(
\r
47 g => g.ToLookup(t => t.Namespace ?? String.Empty, StringComparer.OrdinalIgnoreCase),
\r
48 StringComparer.OrdinalIgnoreCase);
\r
54 private static List<Type> GetAllControllerTypes(IBuildManager buildManager) {
\r
55 // Go through all assemblies referenced by the application and search for
\r
56 // controllers and controller factories.
\r
57 List<Type> controllerTypes = new List<Type>();
\r
58 ICollection assemblies = buildManager.GetReferencedAssemblies();
\r
59 foreach (Assembly assembly in assemblies) {
\r
62 typesInAsm = assembly.GetTypes();
\r
64 catch (ReflectionTypeLoadException ex) {
\r
65 typesInAsm = ex.Types;
\r
67 controllerTypes.AddRange(typesInAsm.Where(IsControllerType));
\r
69 return controllerTypes;
\r
72 public IList<Type> GetControllerTypes(string controllerName, HashSet<string> namespaces) {
\r
73 List<Type> matchingTypes = new List<Type>();
\r
75 ILookup<string, Type> nsLookup;
\r
76 if (_cache.TryGetValue(controllerName, out nsLookup)) {
\r
77 // this friendly name was located in the cache, now cycle through namespaces
\r
78 if (namespaces != null) {
\r
79 foreach (string ns in namespaces) {
\r
80 matchingTypes.AddRange(nsLookup[ns]);
\r
84 // if the namespaces parameter is null, search *every* namespace
\r
85 foreach (var nsGroup in nsLookup) {
\r
86 matchingTypes.AddRange(nsGroup);
\r
91 return matchingTypes;
\r
94 internal static bool IsControllerType(Type t) {
\r
98 t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) &&
\r
100 typeof(IController).IsAssignableFrom(t);
\r