Fix bugs in sizing TableLayoutPanel (Xamarin bug 18638)
[mono.git] / mcs / class / System.Web.Mvc / System.Web.Mvc / ControllerTypeCache.cs
1 /* ****************************************************************************\r
2  *\r
3  * Copyright (c) Microsoft Corporation. All rights reserved.\r
4  *\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
8  *\r
9  * You must not remove this notice, or any other, from this software.\r
10  *\r
11  * ***************************************************************************/\r
12 \r
13 namespace System.Web.Mvc {\r
14     using System;\r
15     using System.Collections;\r
16     using System.Collections.Generic;\r
17     using System.Linq;\r
18     using System.Reflection;\r
19 \r
20     internal sealed class ControllerTypeCache {\r
21 \r
22         private Dictionary<string, ILookup<string, Type>> _cache;\r
23         private object _lockObj = new object();\r
24 \r
25         internal int Count {\r
26             get {\r
27                 int count = 0;\r
28                 foreach (var lookup in _cache.Values) {\r
29                     foreach (var grouping in lookup) {\r
30                         count += grouping.Count();\r
31                     }\r
32                 }\r
33                 return count;\r
34             }\r
35         }\r
36 \r
37         public void EnsureInitialized(IBuildManager buildManager) {\r
38             if (_cache == null) {\r
39                 lock (_lockObj) {\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
46                             g => g.Key,\r
47                             g => g.ToLookup(t => t.Namespace ?? String.Empty, StringComparer.OrdinalIgnoreCase),\r
48                             StringComparer.OrdinalIgnoreCase);\r
49                     }\r
50                 }\r
51             }\r
52         }\r
53 \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
60                 Type[] typesInAsm;\r
61                 try {\r
62                     typesInAsm = assembly.GetTypes();\r
63                 }\r
64                 catch (ReflectionTypeLoadException ex) {\r
65                     typesInAsm = ex.Types;\r
66                 }\r
67                 controllerTypes.AddRange(typesInAsm.Where(IsControllerType));\r
68             }\r
69             return controllerTypes;\r
70         }\r
71 \r
72         public IList<Type> GetControllerTypes(string controllerName, HashSet<string> namespaces) {\r
73             List<Type> matchingTypes = new List<Type>();\r
74 \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
81                     }\r
82                 }\r
83                 else {\r
84                     // if the namespaces parameter is null, search *every* namespace\r
85                     foreach (var nsGroup in nsLookup) {\r
86                         matchingTypes.AddRange(nsGroup);\r
87                     }\r
88                 }\r
89             }\r
90 \r
91             return matchingTypes;\r
92         }\r
93 \r
94         internal static bool IsControllerType(Type t) {\r
95             return\r
96                 t != null &&\r
97                 t.IsPublic &&\r
98                 t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) &&\r
99                 !t.IsAbstract &&\r
100                 typeof(IController).IsAssignableFrom(t);\r
101         }\r
102     }\r
103 }\r