You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在ASP.NET Core MVC中借助Autofac实现属性注入

在ASP.NET Core MVC中用Autofac实现属性注入

看起来你已经走对了大部分路,但可能漏掉了ASP.NET Core MVC控制器激活的关键配置——默认情况下,MVC不会从依赖注入容器中获取控制器实例,而是自己直接实例化,这就导致你注册的PropertiesAutowired()规则没生效。下面是修正后的完整方案:

第一步:确保安装必要的NuGet包

首先得确保你的项目里安装了AutofacAutofac.Extensions.DependencyInjection这两个包,这是Autofac集成ASP.NET Core的基础。

第二步:调整服务配置,让MVC使用容器解析控制器

不管你用哪种方式配置Autofac,核心是要告诉MVC:不要自己创建控制器,从服务容器里拿。这可以通过AddControllersAsServices()方法实现。

推荐方案:使用Autofac的ConfigureContainer(更符合ASP.NET Core规范)

如果是.NET Core 3.x/.NET 5+的项目,推荐用这种方式,把Autofac的配置和原生DI配置分开:

在Program.cs(.NET 6+顶级语句):

var builder = WebApplication.CreateBuilder(args);

// 启用Autofac作为服务提供器工厂
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());

// 添加MVC服务,并指定控制器从容器解析
builder.Services.AddControllersWithViews()
    .AddControllersAsServices();

// 其他原生DI配置...

var app = builder.Build();

// 中间件配置...
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

在Startup.cs(如果用传统Startup类):

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews()
        .AddControllersAsServices(); // 关键:让控制器从服务容器获取实例
}

// Autofac会自动调用这个方法来配置容器
public void ConfigureContainer(ContainerBuilder builder)
{
    // 注册你的服务
    builder.RegisterType<Test2>().As<ITest>();

    // 注册所有控制器,并启用属性注入
    builder.RegisterAssemblyTypes(typeof(Startup).Assembly)
           .Where(t => t.IsController()) // 筛选出所有控制器
           .PropertiesAutowired(); // 开启属性注入
}

替代方案:手动构建容器(适配你原来的代码结构)

如果你更倾向于手动构建容器,只需要在原来的代码里加上AddControllersAsServices(),并确保注册所有控制器:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    // 关键:添加这一行,让MVC从容器获取控制器
    services.AddMvc().AddControllersAsServices();

    ContainerBuilder builder = new ContainerBuilder();
    builder.RegisterType<Test2>().As<ITest>();

    // 注册所有控制器(比单独注册HomeController更灵活)
    builder.RegisterAssemblyTypes(typeof(Startup).Assembly)
           .Where(t => t.IsAssignableTo<Controller>())
           .PropertiesAutowired();

    builder.Populate(services);
    var container = builder.Build();

    // 你的测试代码可以保留,验证注入是否生效
    HomeController test2 = container.Resolve<HomeController>();
    return new AutofacServiceProvider(container);
}

最后要注意的细节

  • 被注入的属性必须是public的,Autofac无法注入私有/受保护的属性。比如你的HomeController里需要这样定义属性:
    public class HomeController : Controller
    {
        public ITest Test { get; set; } // 必须是public才能被注入
    
        // ...
    }
    
  • 如果你只需要给特定控制器开启属性注入,也可以单独注册:builder.RegisterType<HomeController>().PropertiesAutowired();,但注册整个程序集的控制器更省心。

这样调整后,MVC在创建控制器时就会通过Autofac来解析,属性注入就能正常工作了。

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

火山引擎 最新活动