Приведение отправителя события для поиска значения в словаре, который запустил событие - PullRequest
0 голосов
/ 05 мая 2018

В моем классе у меня есть частный словарь 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 голосов
/ 05 мая 2018

Это действительно работает как есть. Одним из улучшений может быть обертывание информации о событии PropertyChanged в новый пользовательский event и новый собственный EventArgs, в котором есть экземпляры Name и opcVariable этого события. Таким образом вы избежите любого приведения, который может привести к ошибке во время выполнения.

Вот пример 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));            
}

Не забудьте отменить подписку на событие, когда ваш основной класс расположен во избежание утечек памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...