总览
| # | 方式 | 使用场景 | 推荐度 |
|---|---|---|---|
| 1 | 构造函数注入 | Controller、Service、ViewComponent | ⭐⭐⭐⭐⭐ |
| 2 | Action 方法参数注入 | Controller Action | ⭐⭐⭐⭐ |
| 3 |
@inject 指令 |
Razor 视图 | ⭐⭐⭐ |
| 4 | HttpContext.RequestServices |
手动获取(不推荐常用) | ⭐⭐ |
| 5 |
IServiceProvider / IServiceScopeFactory
|
后台任务、动态创建 | ⭐⭐⭐ |
| 6 | Middleware 的 Invoke 参数 |
中间件 | ⭐⭐⭐⭐ |
| 7 | ActivatorUtilities |
手动 new 对象时 | ⭐⭐ |
| 8 | 属性注入 [FromServices]
|
Controller 属性 | ⭐⭐ |
1. 构造函数注入(最主流)
public class HomeController : Controller
{
private readonly IFriendService _friendService;
private readonly ILogger _logger;
// ✅ 通过构造函数注入,框架自动解析
public HomeController(IFriendService friendService, ILogger logger)
{
_friendService = friendService;
_logger = logger;
}
public async Task Index()
{
var friends = await _friendService.GetAllAsync();
return View(friends);
}
}
适用于:Controller、Service、Repository、ViewComponent、Middleware 类、HostedService 等所有由 DI 容器管理的类。
2. Action 方法参数注入
public class HomeController : Controller
{
// ✅ 只在某个 Action 中需要,不必污染构造函数
public async Task Friends([FromServices] IFriendService friendService)
{
var friends = await friendService.GetAllAsync();
return View(friends);
}
}
[FromServices] 可省略(ASP.NET Core 对接口类型参数默认从 DI 解析),但写上更明确。
3. Razor 视图中@inject
@using MyApp.Services @inject IFriendService FriendService @inject IOptions Settings好友数:@await FriendService.GetCountAsync()
应用名称:@Settings.Value.AppName
视图中尽量只做简单取值,不要写复杂业务逻辑,否则应改用 ViewComponent。
4. 从HttpContext.RequestServices手动获取
public class HomeController : Controller
{
public IActionResult Index()
{
// ⚠️ 不推荐,但在某些特殊场景下不得不用
var friendService = HttpContext.RequestServices.GetRequiredService();
var friends = friendService.GetAll();
return View(friends);
}
}
典型使用场景:在静态方法、事件回调、或无法使用构造函数注入的地方。
5. 注入IServiceProvider/IServiceScopeFactory
public class OrderProcessingService : IOrderProcessingService
{
private readonly IServiceScopeFactory _scopeFactory;
public OrderProcessingService(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public async Task ProcessOrderAsync(int orderId)
{
// ✅ 在后台线程中创建新的作用域(因为 Scoped 服务不能跨线程共享)
using var scope = _scopeFactory.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService();
var order = await dbContext.Orders.FindAsync(orderId);
// ...
}
}
典型场景:BackgroundService、Timer 回调、Task.Run 中需要 Scoped 服务。
6. Middleware 的Invoke/InvokeAsync参数注入
public class RequestLoggingMiddleware
{
private readonly RequestDelegate _next;
// 构造函数:只能注入 Singleton 服务
public RequestLoggingMiddleware(RequestDelegate next)
{
_next = next;
}
// ✅ Invoke 方法参数:可以注入 Scoped/Transient 服务(每次请求解析)
public async Task InvokeAsync(HttpContext context, ILogger logger)
{
logger.LogInformation("Request: {Path}", context.Request.Path);
await _next(context);
}
}
7.ActivatorUtilities(手动创建实例)
// 当你需要手动 new 一个类,但又想让 DI 帮你注入依赖 var myService = ActivatorUtilities.CreateInstance(serviceProvider, "额外参数");
典型场景:工厂模式、动态创建类型实例。
8. 属性注入([FromServices])
public class HomeController : Controller
{
// ✅ 属性注入(仅 Controller 支持)
[FromServices]
public IFriendService FriendService { get; set; }
public IActionResult Index()
{
var friends = FriendService.GetAll();
return View(friends);
}
}
不推荐,隐藏了依赖关系,不利于测试。
选择指南
你在哪里需要服务?
│
├── Controller / Service / ViewComponent / HostedService
│ → ✅ 构造函数注入
│
├── 只有某一个 Action 需要
│ → ✅ [FromServices] 方法参数注入
│
├── Razor 视图中简单取值
│ → ✅ @inject(复杂逻辑改用 ViewComponent)
│
├── Middleware
│ → 构造函数(Singleton)+ Invoke 参数(Scoped)
│
├── 后台线程 / Timer / Task.Run
│ → ✅ IServiceScopeFactory.CreateScope()
│
├── 静态方法 / 无法注入的地方
│ → ⚠️ HttpContext.RequestServices(最后手段)
│
└── 手动 new 对象
→ ActivatorUtilities.CreateInstance()
常见陷阱
| 陷阱 | 说明 |
|---|---|
| Singleton 中注入 Scoped | ❌ 会导致 Scoped 服务变成 Singleton 生命周期(Captive Dependency) |
在 Task.Run 中直接用构造函数注入的 DbContext |
❌ 跨线程不安全,应用 IServiceScopeFactory 新建作用域 |
在视图中 @inject 后写大量业务逻辑 |
❌ 应抽到 ViewComponent 或 ViewModel 中 |
用 GetService() 不判空 |
⚠️ 服务未注册时返回 null,应用 GetRequiredService() 直接抛异常 |
以上就是ASP.NET Core中获取注入服务的所有方式的详细内容,更多关于ASP.NET Core获取注入服务的资料请关注IT俱乐部其它相关文章!
