C#如何实现多类myField字段在条件触发后一次性更新并保持恒定
解决方案:基于观察者模式的状态同步实现
针对你的需求,我们可以通过让类A成为可观察的状态持有者,结合观察者模式实现所有类的myField在条件触发后自动更新一次并保持恒定。下面是具体的实现方案:
第一步:重构类A,添加状态管理与通知能力
我们需要让类A负责缓存两种状态下的计算结果(条件false和true),并在条件变化时通知所有依赖它的类更新字段,同时确保线程安全避免多线程下的重复触发。
public class A { // 缓存两种状态的计算结果 private Dictionary<string, double>? _initialResult; private Dictionary<string, double>? _updatedResult; // 标记条件是否已触发(仅允许触发一次) private bool _conditionTriggered = false; // 线程安全锁 private readonly object _lockObj = new object(); // 定义条件变化事件,通知订阅者执行更新 public event Action? OnConditionChanged; // 假设param1、param2是全局固定值,这里作为示例字段(可根据实际场景调整) private readonly double _fixedParam1 = 1.0; private readonly double _fixedParam2 = 2.0; /// <summary> /// 获取当前状态对应的计算结果 /// </summary> public Dictionary<string, double> GetCurrentResult(double param3, double param4) { lock (_lockObj) { if (!_conditionTriggered) { _initialResult ??= CalculateInitialResult(); return _initialResult; } else { _updatedResult ??= CalculateUpdatedResult(param3, param4); return _updatedResult; } } } /// <summary> /// 触发条件变化(仅执行一次) /// </summary> public void TriggerCondition(double param3, double param4) { lock (_lockObj) { if (_conditionTriggered) return; _conditionTriggered = true; // 提前计算并缓存更新后的结果 _updatedResult = CalculateUpdatedResult(param3, param4); // 通知所有订阅者执行更新 OnConditionChanged?.Invoke(); } } // 原methodA的逻辑(条件false时) private Dictionary<string, double> CalculateInitialResult() { var result = new Dictionary<string, double>(); // 替换为你原来的计算逻辑 result["key1"] = _fixedParam1 + _fixedParam2; return result; } // 新的计算逻辑(条件true时) private Dictionary<string, double> CalculateUpdatedResult(double param3, double param4) { var result = new Dictionary<string, double>(); // 替换为你新增的带param3、param4的计算逻辑 result["key1"] = _fixedParam1 + _fixedParam2 + param3 + param4; return result; } }
第二步:修改B、C等依赖类,订阅状态变化事件
每个依赖类需要在初始化时获取初始结果,并订阅类A的条件变化事件,一旦事件触发就更新myField,并立即取消订阅(确保仅更新一次)。
public class B { private Dictionary<string, double> _myField; private readonly A _aInstance; // 推荐通过依赖注入获取A的单例实例(确保所有类共享同一个A实例) public B(A aInstance, double initialParam3, double initialParam4) { _aInstance = aInstance; // 初始化时获取条件false的结果 _myField = _aInstance.GetCurrentResult(initialParam3, initialParam4); // 订阅条件变化事件 _aInstance.OnConditionChanged += UpdateMyFieldOnce; } private void UpdateMyFieldOnce() { // 获取更新后的结果(A已缓存,此处参数不影响最终结果) _myField = _aInstance.GetCurrentResult(0, 0); // 取消订阅,避免重复更新 _aInstance.OnConditionChanged -= UpdateMyFieldOnce; } // 示例业务方法,使用myField public void PrintMyField() { foreach (var kvp in _myField) { Console.WriteLine($"B类的myField: {kvp.Key} = {kvp.Value}"); } } }
第三步:使用方式(确保A是单例)
为了让所有B、C等类共享同一个A实例,推荐使用依赖注入将A注册为单例:
// 以.NET Core DI为例 var services = new ServiceCollection(); services.AddSingleton<A>(); services.AddTransient<B>(); // 生命周期可根据业务需求调整 var serviceProvider = services.BuildServiceProvider(); // 获取B实例 var bInstance = serviceProvider.GetRequiredService<B>(); bInstance.PrintMyField(); // 输出初始结果 // 在业务逻辑中触发条件变化 var aInstance = serviceProvider.GetRequiredService<A>(); aInstance.TriggerCondition(3.0, 4.0); bInstance.PrintMyField(); // 输出更新后的结果
方案优势
- 单一职责:类A负责状态管理和结果计算,依赖类专注于自身业务逻辑
- 自动同步:条件触发后所有依赖类自动更新
myField,无需手动遍历实例 - 性能优化:结果缓存机制避免重复计算,事件仅触发一次,更新后自动取消订阅
- 线程安全:通过锁确保状态变化和事件触发的线程安全性
内容的提问来源于stack exchange,提问作者MehdiB
相关产品推荐
相关产品推荐

