Controller Factory 是 ASP.NET MVC 負責建立 Controller 實例的核心擴展點。預設 DefaultControllerFactory 使用 Activator.CreateInstance 需要無參數建構函式,無法支援建構函式注入。自訂 Controller Factory 可整合 DI 容器(Unity、Autofac、Ninject 等)實現依賴注入。
public class HomeController : Controller {
private readonly IProductService _service;
public HomeController(IProductService service) { // 有參數建構函式
_service = service;
}
}
直接執行會拋出:MissingMethodException: No parameterless constructor defined for this object。

public class UnityControllerFactory : DefaultControllerFactory {
private readonly IUnityContainer _container;
public UnityControllerFactory(IUnityContainer container) {
_container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
if (controllerType == null) {
throw new HttpException(404, $"找不到控制器: {requestContext.RouteData.Values["controller"]}");
}
// 從容器解析,支援建構函式注入
return (IController)_container.Resolve(controllerType);
}
}
// Global.asax
public class MvcApplication : HttpApplication {
private static IUnityContainer _container;
protected void Application_Start() {
_container = new UnityContainer();
RegisterTypes(_container);
ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(_container));
RegisterRoutes(RouteTable.Routes);
}
private void RegisterTypes(IUnityContainer container) {
container.RegisterType();
container.RegisterType();
// 註冊 Controller 本身(可選,生命週期管理)
container.RegisterType(new TransientLifetimeManager());
}
}
| 方式 | 優點 | 缺點 |
|---|---|---|
| 繼承 DefaultControllerFactory | 保留預設尋找邏輯(命名空間慣例、Area 支援),僅覆寫實例化 | 受限於基底類別設計 |
| 實作 IControllerFactory | 完全控制尋找與建立流程 | 需自行實作命名空間搜尋、快取等邏輯 |
public class MultiTenantControllerFactory : DefaultControllerFactory {
protected override Type GetControllerType(RequestContext requestContext, string controllerName) {
// 依租戶/區域動態決定命名空間
string tenant = requestContext.RouteData.Values["tenant"] as string;
string[] namespaces = tenant != null
? new[] { $"MyApp.Tenants.{tenant}.Controllers" }
: new[] { "MyApp.Controllers" };
return base.GetControllerType(requestContext, controllerName, namespaces);
}
}
ASP.NET Core 內建 DI 容器,Controller 直接支援建構函式注入,無需自訂 Factory。遷移時可直接移除自訂 Factory 代碼,改用 services.AddControllers() 並註冊服務至 IServiceCollection。
ControllerBuilder.Current.SetControllerFactory 註冊