You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何ControllerActivatorProvider用Type.EmptyTypes创建激活器且支持带参控制器?

为什么ActivatorUtilities.CreateFactory传入Type.EmptyTypes仍能创建带参数的控制器?

首先要明确ActivatorUtilities.CreateFactory第二个参数的核心含义:它不是指定目标类型的所有构造函数参数类型,而是指定你想要手动传入的参数类型列表。当传入Type.EmptyTypes时,相当于告诉工具:所有构造函数需要的参数,都从提供的IServiceProvider中自动解析获取,不需要手动传递任何参数。

具体执行逻辑

看你给出的源码片段:

public Func<ControllerContext, object> CreateActivator(ControllerActionDescriptor descriptor)
{
   var controllerType = descriptor.ControllerTypeInfo?.AsType();

   // ...
 
   var typeActivator = ActivatorUtilities.CreateFactory(controllerType, Type.EmptyTypes);
   return controllerContext => typeActivator(controllerContext.HttpContext.RequestServices, arguments: null);
}

这里的typeActivator是一个工厂委托,调用它时传入了当前请求的DI容器(controllerContext.HttpContext.RequestServices),并且arguments设为null。

以你的HomeController为例:

public class HomeController: Controller
{
    IUserRepository userRepo;
    public HomeController(IUserRepository userRepo)
    {
        this.userRepo = userRepo;
    }
}

当工厂委托执行时,ActivatorUtilities会完成以下步骤:

  1. 分析HomeController的构造函数,识别出它需要的参数类型IUserRepository;
  2. 从传入的DI容器中查找已注册的IUserRepository实例;
  3. 用找到的实例作为参数,调用构造函数创建HomeController对象。

何时需要传入非空参数类型列表?

只有当你想手动提供部分构造函数参数,剩下的由DI容器解析时,才需要在第二个参数里指定手动传入的参数类型。比如控制器构造函数是:

public HomeController(IUserRepository userRepo, string customParam)
{
    this.userRepo = userRepo;
    this.customParam = customParam;
}

此时如果想让userRepo由DI解析,customParam手动传入,就需要这样写:

var typeActivator = ActivatorUtilities.CreateFactory(controllerType, new[] { typeof(string) });
// 调用时手动传入customParam
return controllerContext => typeActivator(controllerContext.HttpContext.RequestServices, new object[] { "手动传入的参数" });

回到ASP.NET Core的源码场景,控制器的所有依赖都应该由DI容器管理,因此不需要手动传入任何参数,使用Type.EmptyTypes完全合理。

内容的提问来源于stack exchange,提问作者user16276760

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 11:00:48