控制台应用DI实践疑问:JSON转验证后POCO的依赖注入
控制台应用DI实现与Mock解决方案
问题1:解耦SomeService以支持Mock
要实现解耦并方便Mock,核心是依赖抽象而非具体实现,步骤如下:
为SomeService定义抽象接口
创建包含业务方法的ISomeService接口,让SomeService实现该接口:public interface ISomeService { // 定义SomeService对外暴露的业务方法,例如: void ExecuteBusinessLogic(); } public class SomeService : ISomeService { private readonly MyPOCO _config; public SomeService(MyPOCO config) { _config = config; } public void ExecuteBusinessLogic() { // 业务逻辑实现 } }通过DI容器获取服务实例
不再直接new SomeService(),而是从DI容器获取ISomeService实例。测试时可以用Mock框架(如Moq)创建ISomeService的模拟实现:// 测试代码示例 var testConfig = new MyPOCO { /* 测试用配置数据 */ }; var mockService = new Mock<ISomeService>(); // 配置Mock方法的行为 mockService.Setup(s => s.ExecuteBusinessLogic()).Verifiable(); // 将Mock实例注入待测试类 var testedClass = new TargetTestClass(mockService.Object);
问题2:注入验证后的MyPOCO及依赖它的SomeService
完全可以将验证后的MyPOCO注入DI容器,同时注册依赖它的SomeService,具体实现:
注册验证后的MyPOCO为单例
先完成配置加载与验证,再将合格的实例注册到DI容器:public static void Main(string[] args) { // 检查配置文件是否存在 if (!File.Exists(args[0])) { // 处理文件不存在的异常逻辑 return; } // 加载并验证配置 IConfigurationRoot config = new ConfigurationBuilder() .AddJsonFile(args[0]) .Build(); MyPOCO poco = new(); config.BindValidate(poco); // 验证失败会抛出异常 // 构建DI容器 var services = new ServiceCollection(); // 注册验证后的MyPOCO为单例(配置在应用生命周期内不会变化) services.AddSingleton(poco); // 注册SomeService,DI会自动注入MyPOCO实例 services.AddSingleton<ISomeService, SomeService>(); // 获取服务实例并使用 var serviceProvider = services.BuildServiceProvider(); var someService = serviceProvider.GetRequiredService<ISomeService>(); // 执行业务逻辑 someService.ExecuteBusinessLogic(); }注意事项
- 验证逻辑必须在注册DI前完成,避免将无效配置注入服务
- MyPOCO作为配置对象,注册为单例是合理的,符合应用生命周期内配置不变的场景
补充:修正BindValidate扩展方法
原方法中ValidationContext的参数有误,需将this改为instance(静态扩展方法中this指向IConfiguration实例,而非待验证的POCO),修正后代码:
public static class ConfigurationExtensions { public static void BindValidate(this IConfiguration root, object instance) { root.Bind(instance, co => co.BindNonPublicProperties = true); var validationContext = new ValidationContext(instance, null, null); var validationResults = new List<ValidationResult>(); var valid = Validator.TryValidateObject(instance, validationContext, validationResults, true); if(!valid) { var errorMsg = string.Join(Environment.NewLine, validationResults.Select(r => r.ErrorMessage)); throw new InvalidOperationException($"配置验证失败:{errorMsg}"); } } }
内容的提问来源于stack exchange,提问作者user22548444
相关产品推荐
相关产品推荐

