c# ioc 容器有哪些

来源:这里教程网 时间:2026-02-21 17:38:14 作者:

C# 中主流、生产可用的 IOC 容器有 4 个核心选择:Microsoft.Extensions.DependencyInjection(官方内置)、Autofac、Unity、Ninject。其中前两个是当前最推荐的,后两个已基本停止活跃维护或仅用于遗留项目。

Microsoft.Extensions.DependencyInjection 是什么?怎么用?

这是 .NET Core 2.0+ 及所有现代 .NET(5/6/7/8/9)默认集成的轻量级 DI 容器,不是第三方库,而是 SDK 自带。它不支持高级生命周期(如作用域嵌套、命名作用域),但足够支撑绝大多数 Web API、Worker Service 和控制台应用。

注册服务只需调用
builder.Services.AddSingleton<irepository sqlrepository>()</irepository>
等扩展方法
Program.cs
中通过
host.Services.GetService<irepository>()</irepository>
解析
只支持三种生命周期:
AddSingleton
AddScoped
AddTransient
—— 没有
InstancePerMatchingLifetimeScope
这类 Autofac 特性
不能解析构造函数中带非注册参数的类型(比如
public Logger(string name)
会失败,除非显式配置)

Autofac 为什么仍是首选第三方容器?

当项目需要更精细的生命周期控制、模块化注册、属性注入、动态代理或与 ASP.NET Core 深度集成时,Autofac 是目前最成熟、文档最全、社区最活跃的替代方案。

支持
InstancePerLifetimeScope
InstancePerMatchingLifetimeScope("admin")
InstancePerOwned<t>()</t>
等高级作用域模式
可按程序集、命名空间或自定义条件批量注册(
RegisterAssemblyTypes
能无缝替换 Microsoft 默认容器:只需在
Program.cs
调用
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
注意:NuGet 包名是
Autofac.Extensions.DependencyInjection
(用于集成),不是
Autofac
单独引用

Unity 和 Ninject 还能用吗?

不建议新项目使用。Unity 已于 2021 年由微软正式归档(archive),Ninject 自 2020 年起无实质更新,且两者对 .NET 6+ 的泛型主机(Generic Host)支持不完善,容易在

Host.CreateApplicationBuilder
场景下报
InvalidOperationException: No service for type '...' has been registered

如果你正在维护老 WPF 或 .NET Framework 4.x 项目,它们仍可工作 迁移到新项目时,遇到
Resolve<t>()</t>
报错或构造函数注入失败,大概率是容器未正确接管 Host 生命周期
Unity 的
RegisterType<t>().As<i>()</i></t>
语法看似简洁,但调试依赖树非常困难 —— 缺少像 Autofac 的
Resolve<ienumerable>>()</ienumerable>
这种开箱即用的集合解析能力

自己写一个简易 IOC 容器靠谱吗?

仅限学习或极简脚本场景。用

Dictionary<type type></type>
+
Activator.CreateInstance
实现注册/解析,确实几小时就能跑通,但很快会撞墙:

无法处理循环依赖(一调用就栈溢出) 不支持泛型注册(
Register<irepository>>()</irepository>
会失败)
生命周期完全靠手动
new
/
Dispose
管理,没有作用域自动释放机制
没有线程安全保障 —— 多次并发
GetService
可能创建重复单例
private readonly Dictionary<Type, Type> _mappings = new();
public void Register<TService, TImplementation>() where TImplementation : class, TService
{
    _mappings[typeof(TService)] = typeof(TImplementation);
}
public TService GetService<TService>()
{
    var implType = _mappings[typeof(TService)];
    return (TService)Activator.CreateInstance(implType);
}

真正卡住人的从来不是“选哪个容器”,而是什么时候该用作用域、什么时候必须用单例、以及如何让 Worker Service 或中间件里的对象也参与 DI 生命周期——这些细节,比容器名字重要得多。

相关推荐