2012-05-30 115 views
0

我試圖找到創建系統的最佳方法,即可以將事件源添加到管理器類,然後將其重新分派給偵聽器。具體來說,我有許多不同的輸入源(鍵盤輸入源,鼠標輸入源,虛擬鍵盤輸入源等),我希望允許開發人員監聽鍵盤輸入源和輸入上的KeyDown事件經理本身(從任何活動輸入源捕捉此事件)。彙總事件源和重新分派事件的最佳方式

在我最終創建許多「調度」功能時,很容易強行推行一個解決方案,只需在它們經過時重新分派事件,但最終我會產生許多單行功能,並且必須創建新的無論何時將新事件添加到輸入源接口時都會起作用。

我已經考慮過使用lambdas,但我需要一種方法來解除事件,如果輸入源從經理中刪除。我可以將lambda保存在一個字典中,由輸入源鍵入,但許多事件具有不同的arg類,創建多個字典會導致難看。

我想知道如果我錯過了一些簡單的方法來做到這一點,使事情保持乾淨,並保持我需要記下的額外代碼的數量。

僅供參考,這裏是我的工作對象的示例:

public interface IInputSource {} 

public interface IKeyboardInputSource : IInputSource 
{ 
    event EventHandler<KeyboardEventArgs> KeyDown; 
    event EventHandler<KeyboardEventArgs> KeyUp; 
} 

public interface IMouseInputSource : IInputSource 
{ 
    event EventHandler<MouseEventArgs> MouseDown; 
    event EventHandler<MouseEventArgs> MouseUp; 
} 

public class InputManager : IKeyboardInputSource, IMouseInputSource 
{ 
    private List<IInputSource> InputSources; 

    //Event declarations from IKeyboardInputSource and IMouseInputSource 

    public void AddSource(IInputSource source) 
    { 
     InputSources.Add(source); 

     if (source is IKeyboardInputSource) 
     { 
      var keyboardSource = source as IKeyboardInputSource; 
      keyboardSource.KeyDown += SendKeyDown; 
      // Listen for other keyboard events... 
     } 
     if (source is IMouseInputSource) 
     { 
      // Listen for mouse events... 
     } 
    } 

    public void RemoveSource(IInputSource source) 
    { 
     if (source is IKeyboardInputSource) 
     { 
      var keyboardSource = source as IKeyboardInputSource; 
      keyboardSource.KeyDown -= SendKeyDown; 
      // Remove other keyboard events... 
     } 
     if (source is IMouseInputSource) 
     { 
      // Remove mouse events... 
     } 

     InputSources.Remove(source); 
    } 

    private void SendKeyDown(object sender, KeyboardEventArgs e) 
    { 
     if (KeyDown != null) 
      KeyDown(sender, e); 
    } 

    //Other "send" functions 
} 
+0

我應該提到這前面 - 但我工作的項目不允許我使用任何第三方庫,很遺憾。 –

+0

但是,您可以檢查bbvcommon庫中使用的代碼,因爲它是開源的,然後您可以將其複製並將其修改爲您的代碼。這是直接鏈接到源代碼https://github.com/bbvcommon/bbv.Common – Jupaol

+0

好點。我會檢查出來的! –

回答

1

你看的Reactive Extensions(Rx)的框架?看起來像你會問什麼,併爲你提供豐富的功能/ lambda像API來管理和處理事件。

無功擴展器(Rx)是構成使用觀察序列和LINQ風格查詢操作

0

大概就像這將有助於異步和基於事件的程序庫 - 它是一個通用的方法,與直接事件訂閱或通過「匯」界面

interface IInputSource<T> where T : EventArgs 
{ 
    event EventHandler<T> InputEvent; 
} 
interface IInputSink<in T> where T : EventArgs 
{ 
    void InputMessageHandler(object sender, T eventArgs); 
} 

internal class InputManager 
{ 
    private Dictionary<Type, object> _inputSources; 
    private Dictionary<Type, object> _inputSinks; 
    private Dictionary<Type, object> _events; 

    public void AddSource<T>(IInputSource<T> source) where T : EventArgs 
    { 
     _inputSources[typeof(T)] = _inputSources;  //add source 
     _events[typeof(T)] = (EventHandler<T>)Dispatch; //register event for subscribers 

     source.InputEvent += Dispatch; 
     source.InputEvent += Dispatch2; 
    } 


    // Dispatch trough direct event subscriptions; 
    private void Dispatch<T>(object sender, T e) where T : EventArgs 
    { 
     var handler = _events[typeof(T)] as EventHandler<T>; 
     handler.Invoke(sender, e); 
    } 
    // Dispatch trough IInputSink subscriptions; 
    private void Dispatch2<T>(object sender, T e) where T : EventArgs 
    { 
     var sink = _inputSinks[typeof(T)] as IInputSink<T>; 
     sink.InputMessageHandler(sender, e); 
    } 

    //Subscription: Client should provide handler into Subscribe() 
    //or subscribe with IInputSink<MyEvent> implementation (Subscribe2()) 
    public void Subscribe<T>(EventHandler<T> handler) where T : EventArgs 
    { 
     var @event = _events[typeof(T)] as EventHandler<T>; 
     _events[typeof(T)] = @event + handler; 
    } 

    public void Subscribe2<T>(IInputSink<T> sink) where T : EventArgs 
    { 
     _inputSinks[typeof(T)] = sink; 
    } 
} 
class XXXX : EventArgs 
{ 

} 
public class Sink: IInputSink<XXXX> 
{ 
    #region Implementation of IInputSink<in XXXX> 

    public void InputMessageHandler(object sender, XXXX eventArgs) 
    { 
     throw new NotImplementedException(); 
    } 

    #endregion 

    public Sink() 
    { 
     var v = new InputManager(); 
     v.Subscribe<XXXX>(GetInputEvent); 
     v.Subscribe2(this); 
    } 

    private void GetInputEvent(object sender, XXXX xxxx) 
    { 
     throw new NotImplementedException(); 
    } 
}