强制转换事件的发件人以查找触发事件的Dictionary中的值

时间:2018-05-05 05:34:47

标签: c# dictionary .net-4.5

在我的课堂上,我有一个私有的C#字典,其中键是一个字符串,值是一个有PropertyChanged事件的对象。定义如下:

private readonly Dictionary<string, IAlsVariable> m_operatorAudibleSevServerVariables = new Dictionary<string, IAlsVariable>();

在我的构造函数中,我有以下foreach填充Dictionary

        foreach (var clusterManager in clusterManagers)
        {
            var clusterName = clusterManager.Name;
            string opcDataSourceServer = "server/" + clusterName + ":[2:http://www.alstom.com/Transport/Iconis/S2K/Data]<Organizes>2:S2KServer<Organizes>2:S2KTerritoryMngt<Organizes>2:TASSObject<HasComponent>2:OperatorAudibleSev";
            var opcVariable = m_alsApplication.Database.GetVariable(opcDataSourceServer, null);
            opcVariable.PropertyChanged += OpcVariable_PropertyChanged;
            m_operatorAudibleSevServerVariables.Add(clusterManager.Name, opcVariable);                
        }

正如您所看到的,在我将每个变量(值)的实例添加到字典之前,我还订阅了每个变量的PropertyChanged事件。

现在,只要其中一个变量实例触发PropertyChanged事件,就会执行(一个)事件处理程序。问题是我不知道字典中的哪个变量触发了PropertyChanged事件。

我有一个名为UpdateAlarmSound的方法,每当此事件触发时我都需要调用它。我需要传递给这个方法的第一个参数是字典中相关变量的关键字。

我的第一个猜测是转换变量然后使用该值来搜索密钥。但我不知道这是否是可行的方法。下面的代码是我的。它似乎有效,但我有一些疑问,也许还有另一种更好的方法。或者也许我的方式有效,但是错了。也许我应该使用.Equals代替==

private void OpcVariable_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    var opcVariable = sender as IAlsVariable;
    var key = m_operatorAudibleSevServerVariables.FirstOrDefault(x => x.Value == opcVariable).Key;
    UpdateAlarmSound(key, Convert.ToInt32(opcVariableVtqValue));            
}

1 个答案:

答案 0 :(得分:1)

确实有效。一项改进可能是将PropertyChanged事件信息包装在您自己的新自定义event和新EventArgs中,并拥有NameopcVariable实例部分那件事。这样可以避免任何可能导致运行时错误的转换。

以下是EventArgs

的示例
public class YourEventArgs : EventArgs
{
    public string Name {get;set;}

    public int OpcVariableVtqValue  {get;set;}

    // If you still need it.
    public string PropertyName {get;set;}
}

以下是IAlsVariable中所做的更改:

public interface IAlsVariable
{
    event EventHandler<YourEventArgs> YourEvent;
}

现在改变实施:

public class SomeAlsVariableImpl : IAlsVariable
{
    public string Name {get;}

    public event EventHandler<YourEventArgs> YourEvent;

    //  Call this method any time you need to raise the event.
    private void RaiseYourEvent(int opcVariableVtqValue)
    {
        YourEvent?.Invoke(this, new YourEventArgs 
        {
             Name = Name,
             OpcVariableVtqValue = opcVariableVtqValue,
        }
    }
}  

现在,在您的主类中,您需要订阅以下事件:

        foreach (var clusterManager in clusterManagers)
        {
            var clusterName = clusterManager.Name;
            string opcDataSourceServer = "server/" + clusterName + ":[2:http://www.alstom.com/Transport/Iconis/S2K/Data]<Organizes>2:S2KServer<Organizes>2:S2KTerritoryMngt<Organizes>2:TASSObject<HasComponent>2:OperatorAudibleSev";
            var opcVariable = m_alsApplication.Database.GetVariable(opcDataSourceServer, null);
            opcVariable.YourEvent += OpcVariable_YourEvent;
            m_operatorAudibleSevServerVariables.Add(clusterManager.Name, opcVariable);                
        }

然后:

private void OpcVariable_YourEvent(object sender, YourEventArgs e)
{
    UpdateAlarmSound(e.Name, e.OpcVariableVtqValue));            
}

当您的主要课程被处理以避免内存泄漏时,请不要忘记取消订阅该事件。