2009-12-10 50 views
14

Có thể nhận tất cả các bộ điều khiển có sẵn cho ControllerFactory không?
Điều tôi muốn làm là lấy danh sách tất cả các loại bộ điều khiển trong ứng dụng, nhưng theo cách nhất quán.ASP.NET MVC: Nhận tất cả các bộ điều khiển

Vì vậy, tất cả các trình điều khiển tôi nhận được đều giống nhau với độ phân giải yêu cầu mặc định đang sử dụng.

(Nhiệm vụ thực tế là tìm tất cả các phương thức hành động có thuộc tính nhất định).

Trả lời

12

Bạn có thể sử dụng phản ánh để liệt kê tất cả các lớp trong một assembly, và chỉ lọc các lớp kế thừa từ lớp Controller.

Tham chiếu tốt nhất là asp.net mvc source code. Hãy xem các triển khai của các lớp ControllerTypeCacheActionMethodSelector. ControllerTypeCache hiển thị cách nhận tất cả các lớp bộ điều khiển có sẵn.

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

Và ActionMethodSelector cho biết cách kiểm tra xem phương thức có thuộc tính mong muốn hay không.

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

Nội bộ, tôi ước họ không làm theo cách này. Nhưng ok, đây là câu trả lời. –

7

Tôi không nghĩ rằng có thể đưa ra câu trả lời đơn giản cho câu hỏi này, vì nó phụ thuộc vào rất nhiều thứ khác nhau, bao gồm việc triển khai IControllerFactory.

Ví dụ, nếu bạn có IControllerFactory được xây dựng hoàn toàn tùy chỉnh, tất cả các phiên cược sẽ bị tắt, vì nó có thể sử dụng bất kỳ cơ chế nào để tạo các trường hợp Bộ điều khiển.

Tuy nhiên, DefaultControllerFactory xem xét loại Bộ điều khiển thích hợp trong tất cả các cụm được xác định trong RouteCollection (được định cấu hình trong global.asax).

Trong trường hợp này, bạn có thể lặp qua tất cả các cụm được liên kết với RouteCollection và tìm Bộ điều khiển trong mỗi.

Controller Tìm trong một hội đồng đưa ra là tương đối dễ dàng:

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

nơi asm là một ví dụ hội.

Các vấn đề liên quan