2012-06-25 58 views
3

我目前使用的觸發事件,關閉一組代表,我需要能夠防止剩餘的代表從另一個代表中激活。在C#中,如何停止從其綁定代理的事件執行?

以下代碼複製場景...

//nonsense class 
public class Foo { 
    public string Bar { get; set; } 
} 

//nonsense event. 
public event Action<Foo> SomeEvent; 

void BindAndFire() { 
    //wire it up. 
    SomeEvent += (foo) => { 
     var a = DateTime.Now.Millisecond % 2; 
     foo.Bar = (a == 0) ? "Hooray" : "Boo"; 
    }; 
    SomeEvent += (foo) => { 
     if(foo.Bar == "Boo") { 
      SomeEvent.CANCEL_THE_REST(); //what do I do here? 
     } 
    }; 
    SomeEvent += (foo) => { 
     foo.Bar += ", you made it!"; 
    }; 

    //fire the event. 
    SomeEvent(new Foo()); 
} 

鑑於上述情況,有什麼事我需要做什麼?我100%可以更改爲動作列表或其他內容,但似乎我應該能夠阻止後續事件的執行。

注:顯示的代碼只是複製的問題,不是我的程序結構。實際的程序正在處理傳入的網絡事件,並有一個任意代理列表,它運行在他們......我不想發佈一個問題的整個事情。

...也許我只是想使用它們,目的不是要使用的方法,我我很好的是,我只希望我只需要學習一些新的關於C#中事件的事情。

謝謝你的時間!

回答

1

我想我可能已經回答了我的問題。

我最終什麼事做,就是我代表返回一個布爾值,然後當我去執行我的活動,我實際使用GetInvocationList(),以獲得代表,並呼籲他們,檢查返回值...

新的代碼看起來像這樣:

//nonsense class 
public class Foo { 
    public string Bar { get; set; } 
} 

//nonsense event. 
public event Func<Foo, bool> SomeEvent; 

void BindAndFire() { 
    //wire it up. 
    SomeEvent += (foo) => { 
     var a = DateTime.Now.Millisecond % 2; 
     foo.Bar = (a == 0) ? "Hooray" : "Boo"; 
     return true; 
    }; 
    SomeEvent += (foo) => { 
     return foo.Bar != "Boo"; 
    }; 
    SomeEvent += (foo) => { 
     foo.Bar += ", you made it!"; 
     return true; 
    }; 

    //fire the event. 
    var f = new Foo(); 
    foreach(var s in SomeEvent.GetInvocationList()) { 
     if(!s.DynamicInvoke(f)) break; 
    } 
} 

編輯:最後我用我的答案和藍莓的上述的組合,因爲它適合什麼我工作的更好。所以在我的情況下,其中一個事件參數有一個Close()方法,開發人員可以在其委託中調用它,因此在那裏設置了一個屬性,然後在通過GetInvocationList()循環時檢查並斷開它。

//nonsense class 
public class Foo { 
    public string Bar { get; set; } 
    public bool IsClosed { get; private set; } 
    public void Close() { 
     IsClosed = true; 
    } 
} 

//nonsense event. 
public event Action<Foo> SomeEvent; 

void BindAndFire() { 
    //wire it up. 
    SomeEvent += (foo) => { 
     var a = DateTime.Now.Millisecond % 2; 
     foo.Bar = (a == 0) ? "Hooray" : "Boo"; 
    }; 
    SomeEvent += (foo) => { 
     if(foo.Bar != "Boo") { 
      foo.Close(); 
     } 
    }; 
    SomeEvent += (foo) => { 
     foo.Bar += ", you made it!"; 
    }; 

    //fire the event. 
    var f = new Foo(); 
    foreach(var s in SomeEvent.GetInvocationList()) { 
     s.DynamicInvoke(f); 
     if(f.IsClosed) break; 
    } 
} 
+1

我將不得不這樣做的問題是,如果您的代理使用此事件時,它可以得到相當混亂當代表不拉開序幕。明確地檢查它是否已被處理將是我要去的方式(請參閱上面的答案)...爲了清晰起見和被調用的委託自由地完成事件調用所需的內容。但是,如果你不介意這一點,而且這是一個非常具體的代表,那麼這將爲你節省每一個委託方法的'處理完畢'檢查。 – Blueberry

+0

啊,是的,在幾乎所有情況下,我都同意你的說法,這是非常不可預測的行爲。這是一個非常獨特的情況,但是......開發人員實際上期望這種行爲。 –

2

您可以使用類似HandledEventArgs(或使用類似的概念),與此,當事件被處理,你設置的「處理」屬性和您的其他代表查詢此屬性。

不知道你可以強制取消所有其他呼叫,並可以得到,如果你做了以後有些凌亂調試。

+0

哦......我想我明白你在說什麼了。這是個好主意。我會給它一個旋轉...... –

+0

我最終做了兩個我們的答案的組合,因爲它適合我的用例最好的。 –

+0

+1對你的答案肯定,但是,因爲它是非常有幫助的。 –