Fire event when a property or variable changes value

后端 未结 2 1467
长发绾君心
长发绾君心 2021-01-14 03:56

I want to add more functionality to a project I have that makes use a number of classes packaged in the NET Framework. These same classes provide a number of properties whic

2条回答
  •  悲&欢浪女
    2021-01-14 04:42

    I implemented a basic class that should get you started. I'm sure a fully functional, production-ready, thread-safe class would require a bit more work, plus you need to implement your own strategy for when to poll for value changes.

    public class TargettedObserver
    {
        private static readonly EqualityComparer EqualityComparer = EqualityComparer.Default;
    
        private Func ValueTarget;
        private T OldValue;
    
        public event ObservedValueChangedEventHandler ValueChanged;
    
        public TargettedObserver(Func 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(oldValue, newValue));
        }
    
        private static bool CompareValues(T oldValue, T newValue)
        {
            return !EqualityComparer.Equals(oldValue, newValue);
        }
    
        private T ObtainCurrentValue()
        {
            return ValueTarget();
        }
    }
    

    And the event handling:

    public class ObservedValueChangedEventArgs : 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(TargettedObserver observer, ObservedValueChangedEventArgs eventArgs);
    

    Usage looks something like this:

    public class TestClass
    {
        private Socket MySocket;
        private static TargettedObserver SocketConnectedObserver;
    
        public void Main()
        {
            MySocket = new Socket();
            SocketConnectedObserver = new TargettedObserver(() => MySocket.Connected);
            SocketConnectedObserver.ValueChanged += ReportSocketConnectedStateChanged;
            PerformSocketConnection();
    
            MainThread.Invoke(PollSocketValue);
        }
    
        private void PollSocketValue()
        {
            SocketConnectedObserver.CheckValue();
            MainThread.Invoke(PollSocketValue);
        }
    
        private void ReportSocketConnectedStateChanged(TargettedObserver observer, ObservedValueChangedEventArgs eventArgs)
        {
            Console.WriteLine("Socket connection state changed!  OldValue: " + eventArgs.OldValue + ", NewValue: " + eventArgs.NewValue);
        }
    }
    

    Notice the constructor takes a simple lambda expression that can evaluate the value you're wanting to observe.

    Also note that MainThread.Invoke is just a pseudocode to show it polling for a change on every main thread loop. I'm sure there are nicer strategies (background thread with a timer interval) for example that could be implemented in a nice, reusable way. Still more work to be done in terms of deregistering the observer. Could probably make some nice factory methods or lambda delegates so you don't need to keep the TargettedObserver instance floating around and reduce the amount of wiring/manual code. But at least this should be a start.

提交回复
热议问题