如何在ASP.NET Core MVC中借助Autofac实现属性注入
在ASP.NET Core MVC中用Autofac实现属性注入
看起来你已经走对了大部分路,但可能漏掉了ASP.NET Core MVC控制器激活的关键配置——默认情况下,MVC不会从依赖注入容器中获取控制器实例,而是自己直接实例化,这就导致你注册的PropertiesAutowired()规则没生效。下面是修正后的完整方案:
第一步:确保安装必要的NuGet包
首先得确保你的项目里安装了Autofac和Autofac.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




