0

これは非常に長い質問であることが判明したので、それを読んでコメント/回答する時間をあきらめたすべての人に事前に感謝します:)


編集

  • この質問は大幅に簡略化されています。
  • サンプルコードは完全でシンプルなプログラムになりました


インターフェイスを介して実装されたオブザーバーパターンを使用し ています。

public interface IObserver<in T>where T:EventArgs
{
    void Update(object sender, T e);
}

public interface ISubject<in T, TU>where TU:EventArgs
{
    event EventHandler<TU> Notify;

    T State { set; }

    void Attach(Action<object,TU> callback);
    void Detach(Action<object, TU> callback);
}


これらのインターフェイスを実装する2つの単純なクラスを作成しました。オブジェクトでイベントが発生すると、オブジェクトはMyObserverコンソールウィンドウに文字列を出力するだけです。NotifyMySubject

    public class MyObserver:IObserver<TestEventArgs>
    {
        private ISubject<bool, TestEventArgs> _subject;

        public MyObserver(ISubject<bool, TestEventArgs> subject)
        {
            _subject = subject;
        }

        public void Subscribe()
        {
            _subject.Attach(Update);
        }

        public void Unsubscribe()
        {
            _subject.Detach(Update);
        }

        public void Update(object sender, TestEventArgs e)
        {
            Console.WriteLine(e.TestMessage);
        }
    }

    public class MySubject:ISubject<bool, TestEventArgs>
    {
        public void ObservableEvent(string message)
        {
            InvokeNotify(message);
        }

        private void InvokeNotify(string message)
        {
            EventHandler<TestEventArgs> handler = Notify;

            if(handler != null)
            {
                handler(this, new TestEventArgs(message));
            }
        }

        public event EventHandler<TestEventArgs> Notify;

        public bool State
        {
            set { throw new NotImplementedException(); }
        }

        public void Attach(Action<object, TestEventArgs> callback)
        {
            Notify += new EventHandler<TestEventArgs>(callback);
        }

        public void Detach(Action<object, TestEventArgs> callback)
        {
            Notify -= new EventHandler<TestEventArgs>(callback);
        }
    }

    public class TestEventArgs:EventArgs
    {
        public TestEventArgs(string message)
        {
            TestMessage = message;
        }

        public string TestMessage { get; private set; }
    }


このテストプログラムは次のことを示しています。

  • イベントをサブスクライブする前myObserverは、コンソールウィンドウにメッセージは出力されません。
  • myObserverイベントをサブスクライブした後Notify、メッセージはコンソールウィンドウに出力されます。
  • myObserverイベントのサブスクライブを解除した後もNotify、メッセージはコンソールウィンドウに出力されます

    static void Main(string[] args)
    {
        MySubject mySubject = new MySubject();
        MyObserver myObserver = new MyObserver(mySubject);
    
        //we have not subscribed to the event so this should not be output to the console
        mySubject.ObservableEvent("First Test");
    
        myObserver.Subscribe();
    
        //we are now subscribing to the event. This should be displayed on the console window
        mySubject.ObservableEvent("Second Test");
    
        myObserver.Unsubscribe();
    
        //We have unsubscribed from the event. I would not expect this to be displayed
        //...but it is!
        mySubject.ObservableEvent("Third Test");
    
        Console.ReadLine();
    }
    

私が抱えている問題は、購読解除プロセスが機能していないことです。

理由がよくわかりません。


質問

  • 登録解除プロセスが機能しないのはなぜですか?
  • 2つのイベントハンドラーを比較するとどうなりますか?それらはどのように等しいかどうかと定義されていますか?Containsこれは、呼び出しリストメソッドが常にを返す理由に対する答えにつながる可能性がありますfalse
4

1 に答える 1

1

私はあなたの問題がこのコードであると思う:

public void Attach(Action<object, TestEventArgs> callback)
{
    Notify += new EventHandler<TestEventArgs>(callback);
}

Detach対応するコードと同様に、実際に新しいオブジェクトを割り当てます。したがって、切り離されているものは、取り付けられているものと同じではありません。

よくわかりませんが、次のように変更することで修正できる可能性がありAttachますDetach

void Attach(EventHandler<TU> callback);
void Detach(EventHandler<TU> callback);

そして、クライアントコードでは:

public void Attach(EventHandler<TestEventArgs> callback)
{
    Notify += callback;
}

public void Detach(EventHandler<TestEventArgs> callback)
{
    Notify -= callback;
}

私は実際にこれをコンパイルしようとはしていませんが、動作するはずです。

または、コンパイラが型変換を実行できる場合:

public void Attach(Action<object, TestEventArgs> callback)
{
    Notify += callback;
}

一撃の価値があるかもしれません。

于 2011-09-15T17:57:39.887 に答える