我想向我拥有的项目添加更多功能,该项目使用了 NET Framework 中打包的许多类。这些相同的类提供了许多属性,这些属性对于调整我的项目的功能非常有用,但是这些类缺少的一件事是事件。
如果每个属性都有一个适当的事件,每当此类属性的值更改时都会触发该事件,那么我可以分配一个事件处理程序,该事件处理程序将根据这些属性值进行操作。
我在下面做了一个示例案例,以我能想到的最简单的方式说明我的目标。
Sample case:
The
System.Net.Sockets.Socket
class (Socket on MSDN Docs) has a property namedConnected
that basically returns true if the socket is connected to a specified end point otherwise returns false.What I would like to accomplish is simple. I would like to keep this property under "watch" and when the value of it changes, fire a event.
对我自己的一个类(class)这样做很简单,尽管使用 INotifyPropertyChanged interface 有点烦人,仅仅是因为我的代码总是更改属性的值,所以我必须手动触发事件。不幸的是,据我所知,即使是这种过程也不能应用于 NET Framework 中现有的 Socket
类。
嗯,这个问题变得相当广泛,抱歉,但我希望它能帮助我了解我的目标。
现在简单地说,我想观察 Socket
类的 Connected
属性,当它的值发生变化时,触发一个事件。如果也可以使用这种方法来观察变量和属性,那将是非常棒的,不仅对我来说,而且对每个在 SO 上偶然发现这个问题的人都是如此。
当然首选简单轻量级的方法,但最重要的是,我想了解它是如何实现的,以便将来我可以将它大规模应用于其他类。
我意识到我问了很多。非常感谢。
有任何问题都可以问。
最佳答案
我实现了一个基础类,可以帮助您入门。我敢肯定,一个功能齐全、生产就绪、线程安全的类需要做更多的工作,而且您需要实现自己的策略来确定何时轮询值更改。
public class TargettedObserver<T>
{
private static readonly EqualityComparer<T> EqualityComparer = EqualityComparer<T>.Default;
private Func<T> ValueTarget;
private T OldValue;
public event ObservedValueChangedEventHandler<T> ValueChanged;
public TargettedObserver(Func<T> valueTarget)
{
this.ValueTarget = valueTarget;
OldValue = ObtainCurrentValue();
}
public bool CheckValue()
{
T oldValue = OldValue;
T newValue = ObtainCurrentValue();
bool hasValueChanged = CompareValues(oldValue, newValue);
if (hasValueChanged)
{
OldValue = newValue;
NotifyValueChanged(oldValue, newValue);
}
return hasValueChanged;
}
private void NotifyValueChanged(T oldValue, T newValue)
{
var valueChangedEvent = ValueChanged;
if (valueChangedEvent != null)
valueChangedEvent(this, new ObservedValueChangedEventArgs<T>(oldValue, newValue));
}
private static bool CompareValues(T oldValue, T newValue)
{
return !EqualityComparer.Equals(oldValue, newValue);
}
private T ObtainCurrentValue()
{
return ValueTarget();
}
}
事件处理:
public class ObservedValueChangedEventArgs<T> : EventArgs
{
public T OldValue { get; private set; }
public T NewValue { get; private set; }
public ObservedValueChangedEventArgs(T oldValue, T newValue)
{
this.OldValue = oldValue;
this.NewValue = newValue;
}
}
public delegate void ObservedValueChangedEventHandler<T>(TargettedObserver<T> observer, ObservedValueChangedEventArgs<T> eventArgs);
用法看起来像这样:
public class TestClass
{
private Socket MySocket;
private static TargettedObserver<bool> SocketConnectedObserver;
public void Main()
{
MySocket = new Socket();
SocketConnectedObserver = new TargettedObserver<bool>(() => MySocket.Connected);
SocketConnectedObserver.ValueChanged += ReportSocketConnectedStateChanged;
PerformSocketConnection();
MainThread.Invoke(PollSocketValue);
}
private void PollSocketValue()
{
SocketConnectedObserver.CheckValue();
MainThread.Invoke(PollSocketValue);
}
private void ReportSocketConnectedStateChanged(TargettedObserver<bool> observer, ObservedValueChangedEventArgs<bool> eventArgs)
{
Console.WriteLine("Socket connection state changed! OldValue: " + eventArgs.OldValue + ", NewValue: " + eventArgs.NewValue);
}
}
请注意,构造函数采用一个简单的 lambda 表达式,可以评估您想要观察的值。
另请注意,MainThread.Invoke
只是一个伪代码,用于显示它在每个主线程循环中轮询更改。我确信有更好的策略(带有计时器间隔的后台线程),例如可以以一种很好的、可重用的方式实现。在注销观察员方面还有更多工作要做。可能会制作一些不错的工厂方法或 lambda 委托(delegate),这样您就不需要让 TargettedObserver 实例四处 float 并减少接线/手动代码的数量。但至少这应该是一个开始。
关于c# - 当属性或变量改变值时触发事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11253147/