3

NET Framework にパッケージ化された多数のクラスを使用するプロジェクトに、さらに機能を追加したいと考えています。これらの同じクラスは、プロジェクトの機能を適応させるのに非常に役立つ多くのプロパティを提供しますが、これらのクラスに欠けているものの 1 つはイベントです。

各プロパティに、そのようなプロパティの値が変更されるたびに発生する適切なイベントがある場合、それらのプロパティ値に基づいて動作するイベント ハンドラーを割り当てることができます。

私が考えることができる最も簡単な方法で私の目標を説明するために、以下のサンプルケースを作成しました.

サンプルケース:

System.Net.Sockets.Socketクラス ( MSDN DocsのSocket ) にはConnected、ソケットが指定されたエンドポイントに接続されている場合は基本的に true を返し、それ以外の場合は false を返すという名前のプロパティがあります。

私が達成したいことは簡単です。このプロパティを「監視」下に置き、値が変化したときにイベントを発生させたいと思います。

私自身のクラスの 1 つに対してそれを行うのは簡単ですが、 INotifyPropertyChanged インターフェイスを使用するのは少し面倒ですが、単に私のコードが常に手動でイベントを発生させる必要があるプロパティの値を変更するためです。残念ながら、私の知る限りでは、この種の手順でさえ、SocketNET Framework 内に分散された既存のクラスには適用できません。

ええと、この質問は非常に広範になりつつあります。申し訳ありませんが、私の目標への洞察が得られたことを願っています。

簡単に言えばConnected、クラスのプロパティを監視しSocket、その値が変化したときにイベントを発生させたいということです。そして、そのようなアプローチを使用して変数とプロパティを監視することも可能であれば、私だけでなく、SO でこの質問に出くわしたすべての人にとっても素晴らしいことです。

もちろん、シンプルで軽量なアプローチが好まれますが、何よりも、それがどのように行われるかを理解したいので、将来的には他のクラスに大規模に適用できます.

私は多くを求めていることに気づきました。どうもありがとう。

ご不明な点がございましたら、お尋ねください。

4

2 に答える 2

1

開始するための基本的なクラスを実装しました。完全に機能し、本番環境に対応し、スレッドセーフなクラスを作成するには、もう少し作業が必要になると確信しています。さらに、値の変更をいつポーリングするかについて、独自の戦略を実装する必要があります。

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);
    }
}

コンストラクターは、観察したい値を評価できる単純なラムダ式を取ることに注意してください。

MainThread.Invokeまた、すべてのメイン スレッド ループで変更をポーリングすることを示す単なる擬似コードであることに注意してください。たとえば、再利用可能な優れた方法で実装できる、より優れた戦略 (タイマー間隔のあるバックグラウンド スレッド) があると確信しています。オブザーバーの登録解除に関しては、さらに多くの作業が必要です。おそらくいくつかの素敵なファクトリ メソッドまたはラムダ デリゲートを作成できるので、TargettedObserver インスタンスをあちこちに浮かせておく必要がなく、配線/手動コードの量を減らすことができます。しかし、少なくともこれはスタートであるべきです。

于 2012-06-28T23:06:59.837 に答える
0

あなたが探しているのはObserver Patternの実装です。このObservable<T>実装のようなものがうまくいくかもしれません。

.NET 4のIObserver<T>インターフェイスも参照してください。

IObserver<T>およびIObservable<T>インターフェイスは、プッシュベースの通知のための一般化されたメカニズムを提供します。IObservable<T>インターフェイスは、通知を送信するクラス (プロバイダー) を表します。インターフェイスは、IObserver<T>それらを受け取るクラス (オブザーバー) を表します。T通知情報を提供するクラスを表します。

于 2012-06-28T21:40:21.857 に答える