咨询:从JSON配置实例化时为LoginLogic注入IConfiguration的方案
嘿,这个场景我太熟了!你现在的问题是手动用Activator.CreateInstance创建LoginLogic时,没法利用.NET Core的依赖注入自动注入IConfiguration对吧?下面给你几个靠谱的解决思路,按推荐程度排序:
1. 最合规的方案:让DI容器全权接管实例创建
.NET Core的DI容器就是用来解决这种依赖注入问题的,最好的做法是把所有需要注入的服务都注册到容器里,让容器帮你处理依赖链:
第一步:注册服务
在你的Program.cs(.NET 6+)或者Startup.cs(旧版本)里,把ILoginLogic、LoginLogic以及LoginRepository都注册到DI容器:
// 注册仓储层 builder.Services.AddScoped<ILoginRepository, LoginRepository>(); // 注册业务逻辑层 builder.Services.AddScoped<ILoginLogic, LoginLogic>(); // 如果LoginModule也需要依赖,也可以一起注册 builder.Services.AddScoped<ILoginModule, LoginModule>();
第二步:修改GetLoginModule方法
通过构造函数注入IServiceProvider,然后直接从容器中获取ILoginLogic实例,容器会自动帮你注入IConfiguration和LoginRepository:
private readonly IServiceProvider _serviceProvider; private readonly IConfiguration _configuration; private ILoginModule _loginModule; // 构造函数注入需要的服务 public YourClass(IServiceProvider serviceProvider, IConfiguration configuration) { _serviceProvider = serviceProvider; _configuration = configuration; } public ILoginModule GetLoginModule() { if (_loginModule == null) { _loginModule = new LoginModule.LoginModule(_configuration); // 直接从容器获取已注入好依赖的ILoginLogic实例 var loginLogic = _serviceProvider.GetRequiredService<ILoginLogic>(); _loginModule.SetLoginLogic(loginLogic); } return _loginModule; }
这种方式完全符合.NET Core的设计理念,后续如果LoginLogic新增其他依赖,只要注册到容器就行,不需要修改这个方法,扩展性拉满。
2. 临时过渡方案:手动传递构造参数
如果暂时不想改动DI注册逻辑,也可以手动把_configuration传递给LoginLogic的带参构造函数,绕过DI直接创建实例:
public ILoginModule GetLoginModule() { if (loginModule == null) { loginModule = new LoginModule.LoginModule(_configuration); Type loginLogicType = CreateTypeFromConfiguration("LoginModule", "LoginLogic", "MyProject.Modules.LoginModule.Logic.LoginLogic"); // 调用带参构造,手动传入IConfiguration var loginLogic = (ILoginLogic)Activator.CreateInstance(loginLogicType, _configuration); loginModule.SetLoginLogic(loginLogic); } return loginModule; }
不过这个方案不推荐长期用,要是以后LoginLogic的构造函数加了新的依赖(比如把LoginRepository也改成注入的),你就得手动修改这里的代码,维护起来很麻烦。
3. 优化代码设计:让LoginRepository也走依赖注入
顺便提一句,你现在在LoginLogic里手动newLoginRepository的做法也不太符合DI原则,建议把LoginRepository也改成构造注入:
public class LoginLogic : ILoginLogic { private readonly IConfiguration _configuration; private readonly ILoginRepository _loginRepository; // 构造函数注入所有依赖,不再手动new public LoginLogic(IConfiguration configuration, ILoginRepository loginRepository) { _configuration = configuration; _loginRepository = loginRepository; } }
然后把LoginRepository注册到DI容器(就是第一步里的那行代码),这样整个依赖链都由容器管理,代码会更干净、更易测试。
内容的提问来源于stack exchange,提问作者NetDev

