簡體   English   中英

屬性或變量更改值時觸發事件

[英]Fire event when a property or variable changes value

我想為我擁有的項目添加更多功能,該功能使用了NET Framework中打包的許多類。 這些相同的類提供了許多屬性,這些屬性對於調整項目的功能非常有用,但是這些類缺少的一件事是事件。

如果每個屬性都有一個適當的事件,只要該屬性的值更改,該事件就會觸發,那么我可以分配一個事件處理程序,該事件處理程序將基於這些屬性值進行操作。

我做了一個示例案例,用我能想到的最簡單的方法來說明我的目標。

樣品盒:

System.Net.Sockets.Socket類( MSDN Docs上的Socket )具有名為Connected的屬性,如果套接字連接到指定的端點,則該屬性基本上返回true,否則返回false。

我想完成的事情很簡單。 我想將此屬性保留在“監視”下,並在其值更改時觸發一個事件。

對我自己的一個類執行此操作將很簡單,盡管使用INotifyPropertyChanged接口有點 ,只是因為我的代碼總是會更改屬性的值,所以我必須手動觸發該事件。 不幸的是,就我所知,這種方法甚至都不能應用於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委托,因此您無需使TargettedObserver實例保持浮動並減少接線/手動代碼的數量。 但這至少應該是一個開始。

您需要的是觀察者模式的實現。 類似Observable<T>實現可能會起作用。

另請參見.NET 4中的IObserver<T>接口

IObserver<T>IObservable<T>接口提供了基於推送的通知的通用機制。 IObservable<T>接口表示發送通知的類(提供者); IObserver<T>接口表示接收它們的類(觀察者)。 T表示提供通知信息的類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM