如何利用设计模式实现ICheck所有现有及未来实现的逻辑校验
解决方案:使用统一执行器+依赖注入(结合组合模式思想)
你可以通过创建一个统一的校验执行器类,结合依赖注入来自动管理所有ICheck的实现类,这样新增实现类时无需修改原有代码,完美适配未来的扩展需求。
具体实现步骤
1. 补全基础类(如果未定义)
首先确保CheckReturn类已正确定义:
public class CheckReturn { public string ContentType { get; set; } // 可根据需求添加其他属性,如校验状态、错误信息等 }
2. 创建统一校验执行器
这个类负责接收所有ICheck实例,并批量执行校验逻辑:
public class AllChecksExecutor { private readonly IEnumerable<ICheck> _allChecks; // 通过构造函数注入所有ICheck实现类 public AllChecksExecutor(IEnumerable<ICheck> allChecks) { _allChecks = allChecks ?? throw new ArgumentNullException(nameof(allChecks)); } // 批量执行所有校验并返回结果集合 public async Task<IEnumerable<CheckReturn>> RunAllChecks(string fileName) { // 并行执行所有校验任务 var checkTasks = _allChecks.Select(check => check.GetCheckReturn(fileName)); return await Task.WhenAll(checkTasks); } }
3. 注册依赖(以.NET内置DI为例)
在服务注册环节,把所有ICheck实现类和执行器类注册到依赖注入容器中:
// 构建服务集合 var services = new ServiceCollection(); // 注册所有ICheck实现类 services.AddTransient<ICheck, ATypeCheck>(); services.AddTransient<ICheck, BTypeCheck>(); // 未来新增CTypeCheck/DTypeCheck时,只需要添加这行: // services.AddTransient<ICheck, CTypeCheck>(); // 注册统一执行器 services.AddTransient<AllChecksExecutor>(); // 构建服务提供者 var serviceProvider = services.BuildServiceProvider();
4. 在主程序中使用执行器
static async Task Main(string[] args) { // 初始化DI容器 var services = new ServiceCollection(); services.AddTransient<ICheck, ATypeCheck>(); services.AddTransient<ICheck, BTypeCheck>(); services.AddTransient<AllChecksExecutor>(); using var serviceProvider = services.BuildServiceProvider(); // 获取执行器实例 var executor = serviceProvider.GetRequiredService<AllChecksExecutor>(); // 执行所有校验 var allResults = await executor.RunAllChecks("XYZ"); // 处理结果 foreach (var result in allResults) { Console.WriteLine($"校验类型:{result.ContentType}"); } }
备选方案:通过反射自动发现实现类
如果不想使用依赖注入,也可以通过反射自动获取所有ICheck的实现类(适合简单场景):
public static class CheckDiscoveryHelper { public static IEnumerable<ICheck> GetAllCheckImplementations() { var checkInterfaceType = typeof(ICheck); // 扫描当前程序集中所有实现了ICheck的非抽象类 var implementations = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(assembly => assembly.GetTypes()) .Where(type => checkInterfaceType.IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract) .Select(type => (ICheck)Activator.CreateInstance(type)); return implementations; } } // 主程序中使用 static async Task Main(string[] args) { var allChecks = CheckDiscoveryHelper.GetAllCheckImplementations(); var checkTasks = allChecks.Select(check => check.GetCheckReturn("XYZ")); var allResults = await Task.WhenAll(checkTasks); foreach (var result in allResults) { Console.WriteLine($"校验类型:{result.ContentType}"); } }
方案对比
- 依赖注入方案:更优雅,便于控制类的生命周期,支持实现类的构造函数注入(如果后续实现类需要依赖其他服务),推荐在项目中使用。
- 反射方案:无需手动注册,适合小型简单项目,但无法控制实例生命周期,也难以处理带参数的构造函数。
内容的提问来源于stack exchange,提问作者user584018
相关产品推荐
相关产品推荐

