.NET依赖注入:如何避免在服务类中使用new实例化对象
在.NET 8 Blazor Server中通过依赖注入创建带参数的对象并注入ILogger
核心思路
避免直接使用new的关键是利用DI容器的服务提供能力,结合ActivatorUtilities自动注入框架管理的依赖(比如ILogger),同时传递自定义业务参数。
步骤1:定义MyUserClass(构造函数包含依赖与自定义参数)
首先确保MyUserClass的构造函数同时接收需要注入的ILogger和自定义参数:
public class MyUserClass { private readonly ILogger<MyUserClass> _logger; public string UserId { get; } // DI自动注入ILogger,自定义参数由调用时传入 public MyUserClass(ILogger<MyUserClass> logger, string userId) { _logger = logger; UserId = userId; } public void ExecuteUserLogic() { _logger.LogInformation($"执行用户 {UserId} 的业务逻辑"); } }
方法1:通过IServiceProvider直接创建实例(最直接)
在MyService中注入IServiceProvider,使用ActivatorUtilities.CreateInstance方法创建MyUserClass——该方法会自动从DI容器中解析ILogger,同时传入你的自定义参数:
public class MyService : IMyService { private readonly IServiceProvider _serviceProvider; // 注入IServiceProvider public MyService(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public void BatchProcessUsers(List<string> userIds) { foreach (var userId in userIds) { // 创建实例:自动注入ILogger,传入userId参数 var userInstance = ActivatorUtilities.CreateInstance<MyUserClass>(_serviceProvider, userId); userInstance.ExecuteUserLogic(); } } }
方法2:注册工厂委托(适合复杂创建逻辑)
如果MyUserClass的创建逻辑复杂,或者需要集中管理创建规则,可以注册一个工厂委托:
1. 在Program.cs中注册工厂
var builder = WebApplication.CreateBuilder(args); // 注册MyUserClass的工厂:接收userId参数,返回实例 builder.Services.AddTransient<Func<string, MyUserClass>>(sp => { return userId => ActivatorUtilities.CreateInstance<MyUserClass>(sp, userId); }); // 注册你的MyService builder.Services.AddScoped<IMyService, MyService>();
2. 在MyService中注入工厂并使用
public class MyService : IMyService { private readonly Func<string, MyUserClass> _userFactory; // 注入工厂委托 public MyService(Func<string, MyUserClass> userFactory) { _userFactory = userFactory; } public void BatchProcessUsers(List<string> userIds) { foreach (var userId in userIds) { // 直接调用工厂创建实例 var userInstance = _userFactory(userId); userInstance.ExecuteUserLogic(); } } }
关键注意事项
- ILogger自动注册:.NET Core默认已注册
ILogger<T>,无需额外配置即可自动注入。 - 生命周期匹配:如果
MyService是Singleton,不要让MyUserClass依赖Scoped服务(比如HttpContextAccessor),否则会导致生命周期不匹配错误。若必须依赖,需使用IServiceScopeFactory创建独立作用域。 - 无需注册MyUserClass到DI:通过
ActivatorUtilities创建实例时,只要它的依赖(如ILogger)已在DI中注册即可,无需单独注册MyUserClass。
内容的提问来源于stack exchange,提问作者MagicJP
相关产品推荐
相关产品推荐

