转换事件的发送者以在触发事件的字典中查找值
Casting the sender of an event to find the value in a Dictionary that fired the event
在我的 class 中,我有一个私有 C# 字典,其中键是一个字符串,值是一个具有 PropertyChanged
事件的对象。定义如下:
private readonly Dictionary<string, IAlsVariable> m_operatorAudibleSevServerVariables = new Dictionary<string, IAlsVariable>();
在我的构造函数中,我有以下用于填充 Dictionary
:
的 foreach
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));
}
它确实可以正常工作。一项改进可能是将 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,
}
}
}
现在,在您的主 class 中,您需要订阅以下事件:
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));
}
当你的 main class 被处理以避免内存泄漏时,不要忘记取消订阅事件。
在我的 class 中,我有一个私有 C# 字典,其中键是一个字符串,值是一个具有 PropertyChanged
事件的对象。定义如下:
private readonly Dictionary<string, IAlsVariable> m_operatorAudibleSevServerVariables = new Dictionary<string, IAlsVariable>();
在我的构造函数中,我有以下用于填充 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));
}
它确实可以正常工作。一项改进可能是将 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,
}
}
}
现在,在您的主 class 中,您需要订阅以下事件:
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));
}
当你的 main class 被处理以避免内存泄漏时,不要忘记取消订阅事件。