2009-12-10 20 views
14

ControllerFactoryで使用できるすべてのコントローラを取得することは可能ですか?
私がしたいことは、アプリケーション内のすべてのコントローラタイプのリストを一貫した方法で取得することです。ASP.NET MVC:すべてのコントローラを取得

私が得るすべてのコントローラは、デフォルトのリクエスト解決が使用しているものと同じものです。

(実際の作業は、特定の属性を持つすべてのアクションメソッドを見つけることです)。

答えて

12

リフレクションを使用して、アセンブリ内のすべてのクラスを列挙し、コントローラクラスから継承するクラスのみをフィルタすることができます。

ベストリファレンスはasp.net mvc source codeです。 ControllerTypeCacheActionMethodSelectorクラスの実装を見てください。 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); 
        } 
       } 
      } 
     } 

ActionMethodSelectorは、メソッドに目的の属性があるかどうかをチェックする方法を示します。

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

内部、私は彼らがこのようにしなかったことを望む。しかし、これは答えです。 –

7

それはIControllerFactoryの実装など、さまざまなもの、多くの依存するので、私は、それがこの質問に単純な答えを与えることが可能だとは思いません。

たとえば、完全にカスタムIControllerFactoryを実装している場合、コントローラインスタンスを作成するためのの種類のメカニズムが使用される可能性があるため、すべてのベットはオフになっています。

ただし、DefaultControllerFactoryは、RouteCollection(global.asaxで設定されている)で定義されたすべてのアセンブリで適切なController型を探します。

この場合、RouteCollectionに関連付けられているすべてのアセンブリをループし、それぞれのコントローラを探すことができます。特定のアセンブリでコントローラを見つける

は比較的簡単です:

asmは、アセンブリインスタンスである
var controllerTypes = from t in asm.GetExportedTypes() 
         where typeof(IController).IsAssignableFrom(t) 
         select t; 

関連する問題