如何通过事件发送者类型转换获取触发事件的Dictionary对应值
解决思路:通过事件Sender反向查找Dictionary条目
这事儿其实挺 straightforward 的,核心逻辑就是事件的sender参数本身就是触发PropertyChanged的那个IAlsVariable实例,咱们只需要从字典里找到对应这个实例的键值对就行,下面给你两种实用的实现方案:
方案一:直接遍历字典查找(适合小字典场景)
首先在填充字典的时候,记得给每个IAlsVariable实例订阅PropertyChanged事件:
foreach (var clusterManager in clusterManagers) { var clusterName = clusterManager.Name; string opcDataSourceServer = "server/" + ...; // 假设你已经完成了IAlsVariable实例的创建/获取 IAlsVariable variable = CreateOrGetAlsVariable(opcDataSourceServer); // 订阅事件 variable.PropertyChanged += AlsVariable_PropertyChanged; // 添加到私有字典 m_operatorAudibleSevServerVariables.Add(clusterName, variable); }
然后在事件处理方法里,把sender转成IAlsVariable,再用FirstOrDefault反向查找字典里的匹配项:
private void AlsVariable_PropertyChanged(object sender, PropertyChangedEventArgs e) { // 先安全转换sender类型 if (sender is not IAlsVariable changedVariable) { return; } // 查找字典中值为当前实例的键值对 var matchedEntry = m_operatorAudibleSevServerVariables .FirstOrDefault(kv => kv.Value == changedVariable); // 检查是否找到有效条目 if (matchedEntry.Key != null) // 因为键是string,默认值是null,这样判断更直观 { string targetKey = matchedEntry.Key; IAlsVariable targetVariable = matchedEntry.Value; // 这里就可以拿到对应的键和变量,执行你的业务逻辑了 Console.WriteLine($"字典中键为「{targetKey}」的变量,{e.PropertyName} 属性发生了变化"); } else { // 这里可以加日志或者异常处理,比如变量已从字典移除但事件没取消订阅的情况 Console.WriteLine("未找到触发事件的变量对应的字典条目"); } }
方案二:维护反向字典(适合大字典/高频率触发场景)
如果你的字典条目很多,每次遍历查找效率会比较低,这时候可以维护一个反向字典(以IAlsVariable为键,对应的string为值),这样查找就是O(1)的时间复杂度:
首先新增一个私有反向字典:
private readonly Dictionary<string, IAlsVariable> m_operatorAudibleSevServerVariables = new Dictionary<string, IAlsVariable>(); // 新增反向字典,用于快速通过变量实例找对应键 private readonly Dictionary<IAlsVariable, string> m_variableToKeyMap = new Dictionary<IAlsVariable, string>();
填充字典的时候同步更新反向字典:
foreach (var clusterManager in clusterManagers) { var clusterName = clusterManager.Name; string opcDataSourceServer = "server/" + ...; IAlsVariable variable = CreateOrGetAlsVariable(opcDataSourceServer); variable.PropertyChanged += AlsVariable_PropertyChanged; m_operatorAudibleSevServerVariables.Add(clusterName, variable); // 同步添加到反向字典 m_variableToKeyMap.Add(variable, clusterName); }
事件处理方法里直接用反向字典快速查找:
private void AlsVariable_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (sender is IAlsVariable changedVariable && m_variableToKeyMap.TryGetValue(changedVariable, out string targetKey)) { // 直接拿到对应键,效率拉满 Console.WriteLine($"字典中键为「{targetKey}」的变量,{e.PropertyName} 属性发生了变化"); // 如果需要变量实例,也可以从主字典取:m_operatorAudibleSevServerVariables[targetKey] } else { // 处理未找到的情况 Console.WriteLine("未找到触发事件的变量对应的字典条目"); } }
注意事项
- 当你从主字典移除变量的时候,一定要记得取消事件订阅,并同步移除反向字典的条目,否则会导致内存泄漏。
- 如果
IAlsVariable的实例可能被重复添加到字典(虽然你的代码里用的是Add,会抛异常,但还是要注意),要确保反向字典不会出现重复键的问题。
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

