首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET MVC Controller 激活系統詳解:預設實現與 Controller 型別解析機制

     編輯:關於ASP.NET

DefaultControllerFactory 為預設 Controller 工廠,核心挑戰在於從路由解析出的 Controller 名稱(不分大小寫、可能含命名空間通配符)正確匹配到實際 CLR 型別。本文詳細解析其反射掃描、命名空間匹配與型別解析邏輯,並提供自訂 ReflectionControllerFactory 模擬實現。

一、Controller 型別解析核心難點

  • URL 中 Controller 名稱不分大小寫,CLR 型別名稱分大小寫
  • 路由註冊命名空間與 ControllerBuilder.DefaultNamespaces 可能含通配符 *
  • 無法直接由名稱+命名空間構造完整型別名稱載入

二、DefaultControllerFactory 反向解析策略

  1. 啟動時掃描 BuildManager.GetReferencedAssemblies() 所有編譯引用組件
  2. 反射取得所有實作 IController 的型別,建立型別快取清單
  3. 請求時:依路由 RouteData 取得 Controller 名稱與命名空間清單
  4. 在快取清單中篩選:型別名稱匹配(忽略大小寫)且命名空間符合任一註冊命名空間(支援通配符)
  5. 唯一匹配 → 回傳型別;零匹配 → 404;多匹配 → 拋出 InvalidOperationException

三、ReflectionControllerFactory 模擬實現關鍵代碼

public class ReflectionControllerFactory : IControllerFactory
{
    private static List<Type> controllerTypes;
    static ReflectionControllerFactory()
    {
        controllerTypes = new List<Type>();
        foreach (var asm in BuildManager.GetReferencedAssemblies())
            controllerTypes.AddRange(asm.GetTypes().Where(t => typeof(IController).IsAssignableFrom(t)));
    }

    public IController CreateController(RequestContext requestContext, string controllerName)
    {
        var controllerType = GetControllerType(requestContext.RouteData, controllerName);
        if (controllerType == null) throw new HttpException(404, "No controller found");
        return (IController)Activator.CreateInstance(controllerType);
    }

    private static bool IsNamespaceMatch(string requested, string target)
    {
        if (!requested.EndsWith(".*", StringComparison.OrdinalIgnoreCase))
            return string.Equals(requested, target, StringComparison.OrdinalIgnoreCase);
        var prefix = requested.Substring(0, requested.Length - 2);
        return target.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) &&
               (target.Length == prefix.Length || target[prefix.Length] == '.');
    }
    // GetControllerType 完整實現略...
}

四、命名空間回退機制

RouteData.DataTokens["UseNamespaceFallback"] 若為 false,僅使用路由註冊命名空間;若為 true(預設),再嘗試 ControllerBuilder.Current.DefaultNamespaces。此機制支援區域註冊與全域預設命名空間協作。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved